/* * Host-side test harness for the stub's parsing logic. * test 1: parse the LIVE device tree (/sys/firmware/fdt — contains the * /firmware/coreboot node depthcharge injects at boot) and expect * the LBIO table at 0xffed9000, size 0x380 (confirmed independently * via `dtc -I dtb -O dts /sys/firmware/fdt` on this unit). * test 2: synthetic LBIO table exercising find_framebuffer against the * verified struct lb_framebuffer layout. * Build: gcc -O2 -o host_test host_test.c && ./host_test */ #include #include #include #include "main.c" static int fails; static void check(const char *what, unsigned long long got, unsigned long long want) { printf("%-40s %s (got 0x%llx, want 0x%llx)\n", what, got == want ? "PASS" : "FAIL", got, want); if (got != want) fails++; } static void put32(u8 *p, u32 v) { memcpy(p, &v, 4); } static void put64(u8 *p, u64 v) { memcpy(p, &v, 8); } int main(void) { /* --- test 1: live DTB ------------------------------------------------ */ FILE *f = fopen("/sys/firmware/fdt", "rb"); if (!f) { printf("no live /sys/firmware/fdt, skipping test 1\n"); } else { static u8 dtb[1 << 20]; size_t n = fread(dtb, 1, sizeof(dtb), f); fclose(f); printf("loaded live fdt: %zu bytes\n", n); u64 addr; u32 size; int rc = find_coreboot_reg(dtb, &addr, &size); check("find_coreboot_reg found", (unsigned long long)(rc == 0), 1); check("LBIO address", addr, 0xffed9000ull); check("LBIO size", size, 0x380); } /* --- test 2: synthetic coreboot table -------------------------------- */ u8 table[512]; memset(table, 0, sizeof table); memcpy(table, "LBIO", 4); put32(table + 4, 24); /* header_bytes */ put32(table + 20, 3); /* table_entries */ u8 *rec = table + 24; /* record 0: an unrelated tag we must skip (size 16) */ put32(rec, 1); put32(rec + 4, 16); rec += 16; /* record 1: LB_TAG_FRAMEBUFFER */ put32(rec, 0x12); put32(rec + 4, 40); /* record size */ put32(rec + 8, 0x80000000); /* physical_address lo */ put32(rec + 12, 0); /* physical_address hi */ put32(rec + 16, 1920); /* x_resolution */ put32(rec + 20, 1200); /* y_resolution */ put32(rec + 24, 7680); /* bytes_per_line */ rec[28] = 32; /* bits_per_pixel */ rec[29] = 16; rec[30] = 8; /* red */ rec[31] = 8; rec[32] = 8; /* green */ rec[33] = 0; rec[34] = 8; /* blue */ struct fbinfo fb; int rc = find_framebuffer((u64)(unsigned long)table, &fb); check("find_framebuffer rc", (unsigned long long)(rc == 0), 1); check("fb pa", fb.pa, 0x80000000ull); check("fb xres", fb.xres, 1920); check("fb yres", fb.yres, 1200); check("fb bpl", fb.bpl, 7680); check("fb bpp", fb.bpp, 32); check("mkcolor white", mkcolor(&fb, 1, 1, 1), 0x00ffffffull); check("mkcolor red", mkcolor(&fb, 1, 0, 0), 0x00ff0000ull); check("mkcolor yellow", mkcolor(&fb, 1, 1, 0), 0x00ffff00ull); check("mkcolor green", mkcolor(&fb, 0, 1, 0), 0x0000ff00ull); check("mkcolor blue", mkcolor(&fb, 0, 0, 1), 0x000000ffull); /* fill_screen: first and last visible pixel written, nothing past end */ { static u8 fbmem[1200 * 7680 + 64]; memset(fbmem, 0xAA, sizeof fbmem); struct fbinfo f2 = { .pa = (u64)(unsigned long)fbmem, .xres = 1920, .yres = 1200, .bpl = 7680, .bpp = 32, .rpos = 16, .rsize = 8, .gpos = 8, .gsize = 8, .bpos = 0, .bsize = 8 }; fill_screen(&f2, 0x00ffffff); u32 last = *(u32 *)(fbmem + 1199 * 7680 + 1919 * 4); u32 first = *(u32 *)fbmem; check("fill first px", first, 0x00ffffff); check("fill last px", last, 0x00ffffff); check("fill no overflow (past-end untouched)", (unsigned long)fbmem[1200 * 7680 + 32], 0xAA); } /* --- test 3: device-realistic pa==0 record must be accepted ---------- */ /* coreboot 4.14 kukui publishes physical_address = 0; depthcharge's * menu renders through DRAM address 0. Regression guard for the * Round-5 bug (blinking parse_fail on the real device). */ { memset(table, 0, sizeof table); memcpy(table, "LBIO", 4); put32(table + 4, 24); put32(table + 20, 1); u8 *r = table + 24; put32(r, 0x12); put32(r + 4, 48); put32(r + 8, 0); /* physical_address = 0 */ put32(r + 12, 0); put32(r + 16, 1200); /* x */ put32(r + 20, 1920); /* y */ put32(r + 24, 4800); /* bytes_per_line */ r[28] = 32; /* bpp */ r[29] = 16; r[30] = 8; r[31] = 8; r[32] = 8; r[33] = 0; r[34] = 8; struct fbinfo fb0; int rc0 = find_framebuffer((u64)(unsigned long)table, &fb0); check("pa==0 record accepted", (unsigned long long)(rc0 == 0), 1); check("pa==0 fb pa stays 0", fb0.pa, 0); check("pa==0 xres", fb0.xres, 1200); check("pa==0 mkcolor red", mkcolor(&fb0, 1, 0, 0), 0x00ff0000ull); } printf(fails ? "\nFAILED: %d\n" : "\nALL PASS\n", fails); return fails != 0; }