cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

edid-generate.c (15161B)


      1/*
      2 * QEMU EDID generator.
      3 *
      4 * This work is licensed under the terms of the GNU GPL, version 2 or later.
      5 * See the COPYING file in the top-level directory.
      6 */
      7#include "qemu/osdep.h"
      8#include "qemu/bswap.h"
      9#include "hw/display/edid.h"
     10
     11static const struct edid_mode {
     12    uint32_t xres;
     13    uint32_t yres;
     14    uint32_t byte;
     15    uint32_t xtra3;
     16    uint32_t bit;
     17    uint32_t dta;
     18} modes[] = {
     19    /* dea/dta extension timings (all @ 50 Hz) */
     20    { .xres = 5120,   .yres = 2160,   .dta = 125 },
     21    { .xres = 4096,   .yres = 2160,   .dta = 101 },
     22    { .xres = 3840,   .yres = 2160,   .dta =  96 },
     23    { .xres = 2560,   .yres = 1080,   .dta =  89 },
     24    { .xres = 2048,   .yres = 1152 },
     25    { .xres = 1920,   .yres = 1080,   .dta =  31 },
     26
     27    /* additional standard timings 3 (all @ 60Hz) */
     28    { .xres = 1920,   .yres = 1200,   .xtra3 = 10,   .bit = 0 },
     29    { .xres = 1600,   .yres = 1200,   .xtra3 =  9,   .bit = 2 },
     30    { .xres = 1680,   .yres = 1050,   .xtra3 =  9,   .bit = 5 },
     31    { .xres = 1440,   .yres =  900,   .xtra3 =  8,   .bit = 5 },
     32    { .xres = 1280,   .yres = 1024,   .xtra3 =  7,   .bit = 1 },
     33    { .xres = 1280,   .yres =  960,   .xtra3 =  7,   .bit = 3 },
     34    { .xres = 1280,   .yres =  768,   .xtra3 =  7,   .bit = 6 },
     35
     36    { .xres = 1920,   .yres = 1440,   .xtra3 = 11,   .bit = 5 },
     37    { .xres = 1856,   .yres = 1392,   .xtra3 = 10,   .bit = 3 },
     38    { .xres = 1792,   .yres = 1344,   .xtra3 = 10,   .bit = 5 },
     39    { .xres = 1440,   .yres = 1050,   .xtra3 =  8,   .bit = 1 },
     40    { .xres = 1360,   .yres =  768,   .xtra3 =  8,   .bit = 7 },
     41
     42    /* established timings (all @ 60Hz) */
     43    { .xres = 1024,   .yres =  768,   .byte  = 36,   .bit = 3 },
     44    { .xres =  800,   .yres =  600,   .byte  = 35,   .bit = 0 },
     45    { .xres =  640,   .yres =  480,   .byte  = 35,   .bit = 5 },
     46};
     47
     48typedef struct Timings {
     49    uint32_t xfront;
     50    uint32_t xsync;
     51    uint32_t xblank;
     52
     53    uint32_t yfront;
     54    uint32_t ysync;
     55    uint32_t yblank;
     56
     57    uint64_t clock;
     58} Timings;
     59
     60static void generate_timings(Timings *timings, uint32_t refresh_rate,
     61                             uint32_t xres, uint32_t yres)
     62{
     63    /* pull some realistic looking timings out of thin air */
     64    timings->xfront = xres * 25 / 100;
     65    timings->xsync  = xres *  3 / 100;
     66    timings->xblank = xres * 35 / 100;
     67
     68    timings->yfront = yres *  5 / 1000;
     69    timings->ysync  = yres *  5 / 1000;
     70    timings->yblank = yres * 35 / 1000;
     71
     72    timings->clock  = ((uint64_t)refresh_rate *
     73                       (xres + timings->xblank) *
     74                       (yres + timings->yblank)) / 10000000;
     75}
     76
     77static void edid_ext_dta(uint8_t *dta)
     78{
     79    dta[0] = 0x02;
     80    dta[1] = 0x03;
     81    dta[2] = 0x05;
     82    dta[3] = 0x00;
     83
     84    /* video data block */
     85    dta[4] = 0x40;
     86}
     87
     88static void edid_ext_dta_mode(uint8_t *dta, uint8_t nr)
     89{
     90    dta[dta[2]] = nr;
     91    dta[2]++;
     92    dta[4]++;
     93}
     94
     95static int edid_std_mode(uint8_t *mode, uint32_t xres, uint32_t yres)
     96{
     97    uint32_t aspect;
     98
     99    if (xres == 0 || yres == 0) {
    100        mode[0] = 0x01;
    101        mode[1] = 0x01;
    102        return 0;
    103
    104    } else if (xres * 10 == yres * 16) {
    105        aspect = 0;
    106    } else if (xres * 3 == yres * 4) {
    107        aspect = 1;
    108    } else if (xres * 4 == yres * 5) {
    109        aspect = 2;
    110    } else if (xres * 9 == yres * 16) {
    111        aspect = 3;
    112    } else {
    113        return -1;
    114    }
    115
    116    if ((xres / 8) - 31 > 255) {
    117        return -1;
    118    }
    119
    120    mode[0] = (xres / 8) - 31;
    121    mode[1] = ((aspect << 6) | (60 - 60));
    122    return 0;
    123}
    124
    125static void edid_fill_modes(uint8_t *edid, uint8_t *xtra3, uint8_t *dta,
    126                            uint32_t maxx, uint32_t maxy)
    127{
    128    const struct edid_mode *mode;
    129    int std = 38;
    130    int rc, i;
    131
    132    for (i = 0; i < ARRAY_SIZE(modes); i++) {
    133        mode = modes + i;
    134
    135        if ((maxx && mode->xres > maxx) ||
    136            (maxy && mode->yres > maxy)) {
    137            continue;
    138        }
    139
    140        if (mode->byte) {
    141            edid[mode->byte] |= (1 << mode->bit);
    142        } else if (std < 54) {
    143            rc = edid_std_mode(edid + std, mode->xres, mode->yres);
    144            if (rc == 0) {
    145                std += 2;
    146            }
    147        } else if (mode->xtra3 && xtra3) {
    148            xtra3[mode->xtra3] |= (1 << mode->bit);
    149        }
    150
    151        if (dta && mode->dta) {
    152            edid_ext_dta_mode(dta, mode->dta);
    153        }
    154    }
    155
    156    while (std < 54) {
    157        edid_std_mode(edid + std, 0, 0);
    158        std += 2;
    159    }
    160}
    161
    162static void edid_checksum(uint8_t *edid, size_t len)
    163{
    164    uint32_t sum = 0;
    165    int i;
    166
    167    for (i = 0; i < len; i++) {
    168        sum += edid[i];
    169    }
    170    sum &= 0xff;
    171    if (sum) {
    172        edid[len] = 0x100 - sum;
    173    }
    174}
    175
    176static uint8_t *edid_desc_next(uint8_t *edid, uint8_t *dta, uint8_t *desc)
    177{
    178    if (desc == NULL) {
    179        return NULL;
    180    }
    181    if (desc + 18 + 18 < edid + 127) {
    182        return desc + 18;
    183    }
    184    if (dta) {
    185        if (desc < edid + 127) {
    186            return dta + dta[2];
    187        }
    188        if (desc + 18 + 18 < dta + 127) {
    189            return desc + 18;
    190        }
    191    }
    192    return NULL;
    193}
    194
    195static void edid_desc_type(uint8_t *desc, uint8_t type)
    196{
    197    desc[0] = 0;
    198    desc[1] = 0;
    199    desc[2] = 0;
    200    desc[3] = type;
    201    desc[4] = 0;
    202}
    203
    204static void edid_desc_text(uint8_t *desc, uint8_t type,
    205                           const char *text)
    206{
    207    size_t len;
    208
    209    edid_desc_type(desc, type);
    210    memset(desc + 5, ' ', 13);
    211
    212    len = strlen(text);
    213    if (len > 12) {
    214        len = 12;
    215    }
    216    memcpy(desc + 5, text, len);
    217    desc[5 + len] = '\n';
    218}
    219
    220static void edid_desc_ranges(uint8_t *desc)
    221{
    222    edid_desc_type(desc, 0xfd);
    223
    224    /* vertical (50 -> 125 Hz) */
    225    desc[5] =  50;
    226    desc[6] = 125;
    227
    228    /* horizontal (30 -> 160 kHz) */
    229    desc[7] =  30;
    230    desc[8] = 160;
    231
    232    /* max dot clock (2550 MHz) */
    233    desc[9] = 2550 / 10;
    234
    235    /* no extended timing information */
    236    desc[10] = 0x01;
    237
    238    /* padding */
    239    desc[11] = '\n';
    240    memset(desc + 12, ' ', 6);
    241}
    242
    243/* additional standard timings 3 */
    244static void edid_desc_xtra3_std(uint8_t *desc)
    245{
    246    edid_desc_type(desc, 0xf7);
    247    desc[5] = 10;
    248}
    249
    250static void edid_desc_dummy(uint8_t *desc)
    251{
    252    edid_desc_type(desc, 0x10);
    253}
    254
    255static void edid_desc_timing(uint8_t *desc, uint32_t refresh_rate,
    256                             uint32_t xres, uint32_t yres,
    257                             uint32_t xmm, uint32_t ymm)
    258{
    259    Timings timings;
    260    generate_timings(&timings, refresh_rate, xres, yres);
    261    stl_le_p(desc, timings.clock);
    262
    263    desc[2] = xres   & 0xff;
    264    desc[3] = timings.xblank & 0xff;
    265    desc[4] = (((xres   & 0xf00) >> 4) |
    266               ((timings.xblank & 0xf00) >> 8));
    267
    268    desc[5] = yres   & 0xff;
    269    desc[6] = timings.yblank & 0xff;
    270    desc[7] = (((yres   & 0xf00) >> 4) |
    271               ((timings.yblank & 0xf00) >> 8));
    272
    273    desc[8] = timings.xfront & 0xff;
    274    desc[9] = timings.xsync  & 0xff;
    275
    276    desc[10] = (((timings.yfront & 0x00f) << 4) |
    277                ((timings.ysync  & 0x00f) << 0));
    278    desc[11] = (((timings.xfront & 0x300) >> 2) |
    279                ((timings.xsync  & 0x300) >> 4) |
    280                ((timings.yfront & 0x030) >> 2) |
    281                ((timings.ysync  & 0x030) >> 4));
    282
    283    desc[12] = xmm & 0xff;
    284    desc[13] = ymm & 0xff;
    285    desc[14] = (((xmm & 0xf00) >> 4) |
    286                ((ymm & 0xf00) >> 8));
    287
    288    desc[17] = 0x18;
    289}
    290
    291static uint32_t edid_to_10bit(float value)
    292{
    293    return (uint32_t)(value * 1024 + 0.5);
    294}
    295
    296static void edid_colorspace(uint8_t *edid,
    297                            float rx, float ry,
    298                            float gx, float gy,
    299                            float bx, float by,
    300                            float wx, float wy)
    301{
    302    uint32_t red_x   = edid_to_10bit(rx);
    303    uint32_t red_y   = edid_to_10bit(ry);
    304    uint32_t green_x = edid_to_10bit(gx);
    305    uint32_t green_y = edid_to_10bit(gy);
    306    uint32_t blue_x  = edid_to_10bit(bx);
    307    uint32_t blue_y  = edid_to_10bit(by);
    308    uint32_t white_x = edid_to_10bit(wx);
    309    uint32_t white_y = edid_to_10bit(wy);
    310
    311    edid[25] = (((red_x   & 0x03) << 6) |
    312                ((red_y   & 0x03) << 4) |
    313                ((green_x & 0x03) << 2) |
    314                ((green_y & 0x03) << 0));
    315    edid[26] = (((blue_x  & 0x03) << 6) |
    316                ((blue_y  & 0x03) << 4) |
    317                ((white_x & 0x03) << 2) |
    318                ((white_y & 0x03) << 0));
    319    edid[27] = red_x   >> 2;
    320    edid[28] = red_y   >> 2;
    321    edid[29] = green_x >> 2;
    322    edid[30] = green_y >> 2;
    323    edid[31] = blue_x  >> 2;
    324    edid[32] = blue_y  >> 2;
    325    edid[33] = white_x >> 2;
    326    edid[34] = white_y >> 2;
    327}
    328
    329static uint32_t qemu_edid_dpi_from_mm(uint32_t mm, uint32_t res)
    330{
    331    return res * 254 / 10 / mm;
    332}
    333
    334uint32_t qemu_edid_dpi_to_mm(uint32_t dpi, uint32_t res)
    335{
    336    return res * 254 / 10 / dpi;
    337}
    338
    339static void init_displayid(uint8_t *did)
    340{
    341    did[0] = 0x70; /* display id extension */
    342    did[1] = 0x13; /* version 1.3 */
    343    did[2] = 4;    /* length */
    344    did[3] = 0x03; /* product type (0x03 == standalone display device) */
    345    edid_checksum(did + 1, did[2] + 4);
    346}
    347
    348static void qemu_displayid_generate(uint8_t *did, uint32_t refresh_rate,
    349                                    uint32_t xres, uint32_t yres,
    350                                    uint32_t xmm, uint32_t ymm)
    351{
    352    Timings timings;
    353    generate_timings(&timings, refresh_rate, xres, yres);
    354
    355    did[0] = 0x70; /* display id extension */
    356    did[1] = 0x13; /* version 1.3 */
    357    did[2] = 23;   /* length */
    358    did[3] = 0x03; /* product type (0x03 == standalone display device) */
    359
    360    did[5] = 0x03; /* Detailed Timings Data Block */
    361    did[6] = 0x00; /* revision */
    362    did[7] = 0x14; /* block length */
    363
    364    did[8]  = timings.clock  & 0xff;
    365    did[9]  = (timings.clock & 0xff00) >> 8;
    366    did[10] = (timings.clock & 0xff0000) >> 16;
    367
    368    did[11] = 0x88; /* leave aspect ratio undefined */
    369
    370    stw_le_p(did + 12, 0xffff & (xres - 1));
    371    stw_le_p(did + 14, 0xffff & (timings.xblank - 1));
    372    stw_le_p(did + 16, 0xffff & (timings.xfront - 1));
    373    stw_le_p(did + 18, 0xffff & (timings.xsync - 1));
    374
    375    stw_le_p(did + 20, 0xffff & (yres - 1));
    376    stw_le_p(did + 22, 0xffff & (timings.yblank - 1));
    377    stw_le_p(did + 24, 0xffff & (timings.yfront - 1));
    378    stw_le_p(did + 26, 0xffff & (timings.ysync - 1));
    379
    380    edid_checksum(did + 1, did[2] + 4);
    381}
    382
    383void qemu_edid_generate(uint8_t *edid, size_t size,
    384                        qemu_edid_info *info)
    385{
    386    uint8_t *desc = edid + 54;
    387    uint8_t *xtra3 = NULL;
    388    uint8_t *dta = NULL;
    389    uint8_t *did = NULL;
    390    uint32_t width_mm, height_mm;
    391    uint32_t refresh_rate = info->refresh_rate ? info->refresh_rate : 75000;
    392    uint32_t dpi = 100; /* if no width_mm/height_mm */
    393    uint32_t large_screen = 0;
    394
    395    /* =============== set defaults  =============== */
    396
    397    if (!info->vendor || strlen(info->vendor) != 3) {
    398        info->vendor = "RHT";
    399    }
    400    if (!info->name) {
    401        info->name = "QEMU Monitor";
    402    }
    403    if (!info->prefx) {
    404        info->prefx = 1024;
    405    }
    406    if (!info->prefy) {
    407        info->prefy = 768;
    408    }
    409    if (info->prefx >= 4096 || info->prefy >= 4096) {
    410        large_screen = 1;
    411    }
    412    if (info->width_mm && info->height_mm) {
    413        width_mm = info->width_mm;
    414        height_mm = info->height_mm;
    415        dpi = qemu_edid_dpi_from_mm(width_mm, info->prefx);
    416    } else {
    417        width_mm = qemu_edid_dpi_to_mm(dpi, info->prefx);
    418        height_mm = qemu_edid_dpi_to_mm(dpi, info->prefy);
    419    }
    420
    421    /* =============== extensions  =============== */
    422
    423    if (size >= 256) {
    424        dta = edid + 128;
    425        edid[126]++;
    426        edid_ext_dta(dta);
    427    }
    428
    429    if (size >= 384 && large_screen) {
    430        did = edid + 256;
    431        edid[126]++;
    432        init_displayid(did);
    433    }
    434
    435    /* =============== header information =============== */
    436
    437    /* fixed */
    438    edid[0] = 0x00;
    439    edid[1] = 0xff;
    440    edid[2] = 0xff;
    441    edid[3] = 0xff;
    442    edid[4] = 0xff;
    443    edid[5] = 0xff;
    444    edid[6] = 0xff;
    445    edid[7] = 0x00;
    446
    447    /* manufacturer id, product code, serial number */
    448    uint16_t vendor_id = ((((info->vendor[0] - '@') & 0x1f) << 10) |
    449                          (((info->vendor[1] - '@') & 0x1f) <<  5) |
    450                          (((info->vendor[2] - '@') & 0x1f) <<  0));
    451    uint16_t model_nr = 0x1234;
    452    uint32_t serial_nr = info->serial ? atoi(info->serial) : 0;
    453    stw_be_p(edid +  8, vendor_id);
    454    stw_le_p(edid + 10, model_nr);
    455    stl_le_p(edid + 12, serial_nr);
    456
    457    /* manufacture week and year */
    458    edid[16] = 42;
    459    edid[17] = 2014 - 1990;
    460
    461    /* edid version */
    462    edid[18] = 1;
    463    edid[19] = 4;
    464
    465
    466    /* =============== basic display parameters =============== */
    467
    468    /* video input: digital, 8bpc, displayport */
    469    edid[20] = 0xa5;
    470
    471    /* screen size: undefined */
    472    edid[21] = width_mm / 10;
    473    edid[22] = height_mm / 10;
    474
    475    /* display gamma: 2.2 */
    476    edid[23] = 220 - 100;
    477
    478    /* supported features bitmap: std sRGB, preferred timing */
    479    edid[24] = 0x06;
    480
    481
    482    /* =============== chromaticity coordinates =============== */
    483
    484    /* standard sRGB colorspace */
    485    edid_colorspace(edid,
    486                    0.6400, 0.3300,   /* red   */
    487                    0.3000, 0.6000,   /* green */
    488                    0.1500, 0.0600,   /* blue  */
    489                    0.3127, 0.3290);  /* white point  */
    490
    491    /* =============== established timing bitmap =============== */
    492    /* =============== standard timing information =============== */
    493
    494    /* both filled by edid_fill_modes() */
    495
    496
    497    /* =============== descriptor blocks =============== */
    498
    499    if (!large_screen) {
    500        /* The DTD section has only 12 bits to store the resolution */
    501        edid_desc_timing(desc, refresh_rate, info->prefx, info->prefy,
    502                         width_mm, height_mm);
    503        desc = edid_desc_next(edid, dta, desc);
    504    }
    505
    506    xtra3 = desc;
    507    edid_desc_xtra3_std(xtra3);
    508    desc = edid_desc_next(edid, dta, desc);
    509    edid_fill_modes(edid, xtra3, dta, info->maxx, info->maxy);
    510    /*
    511     * dta video data block is finished at thus point,
    512     * so dta descriptor offsets don't move any more.
    513     */
    514
    515    edid_desc_ranges(desc);
    516    desc = edid_desc_next(edid, dta, desc);
    517
    518    if (desc && info->name) {
    519        edid_desc_text(desc, 0xfc, info->name);
    520        desc = edid_desc_next(edid, dta, desc);
    521    }
    522
    523    if (desc && info->serial) {
    524        edid_desc_text(desc, 0xff, info->serial);
    525        desc = edid_desc_next(edid, dta, desc);
    526    }
    527
    528    while (desc) {
    529        edid_desc_dummy(desc);
    530        desc = edid_desc_next(edid, dta, desc);
    531    }
    532
    533    /* =============== display id extensions =============== */
    534
    535    if (did && large_screen) {
    536        qemu_displayid_generate(did, refresh_rate, info->prefx, info->prefy,
    537                                width_mm, height_mm);
    538    }
    539
    540    /* =============== finish up =============== */
    541
    542    edid_checksum(edid, 127);
    543    if (dta) {
    544        edid_checksum(dta, 127);
    545    }
    546    if (did) {
    547        edid_checksum(did, 127);
    548    }
    549}
    550
    551size_t qemu_edid_size(uint8_t *edid)
    552{
    553    uint32_t exts;
    554
    555    if (edid[0] != 0x00 ||
    556        edid[1] != 0xff) {
    557        /* doesn't look like a valid edid block */
    558        return 0;
    559    }
    560
    561    exts = edid[126];
    562    return 128 * (exts + 1);
    563}