static int do_vbexport_test_diskinfo_flags(uint32_t flags) { int ret = 0; VbDiskInfo *info; uint32_t count, i; ret = VbExDiskGetInfo(&info, &count, flags); if (ret) return ret; if (count == 0) { VbExDebug("No disk found!\n"); } else { VbExDebug("handle byte/lba lba_count f name\n"); for (i = 0; i < count; i++) { VbExDebug("%08lx %-9llu %-10llu %-2lu %s", info[i].handle, info[i].bytes_per_lba, info[i].lba_count, info[i].flags, info[i].name); if ((flags & info[i].flags) != flags) { VbExDebug(" INCORRECT: flag mismatched\n"); ret = 1; } else VbExDebug("\n"); } } return VbExDiskFreeInfo(info, NULL) || ret; }
static int do_vbexport_test_malloc_size(uint32_t size) { char *mem = VbExMalloc(size); int i, line_size; #if CONFIG_ARM line_size = dcache_get_line_size(); #elif defined CACHE_LINE_SIZE line_size = CACHE_LINE_SIZE; #else line_size = __BIGGEST_ALIGNMENT__; #endif VbExDebug("Trying to malloc a memory block for %lu bytes...", size); if ((uintptr_t)mem % line_size != 0) { VbExDebug("\nMemory not algined with a cache line!\n"); VbExFree(mem); return 1; } for (i = 0; i < size; i++) { mem[i] = i % 0x100; } for (i = 0; i < size; i++) { if (mem[i] != i % 0x100) { VbExDebug("\nMemory verification failed!\n"); VbExFree(mem); return 1; } } VbExFree(mem); VbExDebug(" - SUCCESS\n"); return 0; }
static void vboot_wrapper(void *arg) { VbError_t res; struct vboot_context *context; context = arg; gcontext = context; VbExDebug("Calling VbInit()\n"); res = VbInit(context->cparams, &context->handoff->init_params); VbExDebug("VbInit() returned 0x%08x\n", res); if (res != VBERROR_SUCCESS) { if(res == VBERROR_TPM_REBOOT_REQUIRED) { VbExDebug("TPM Reboot Required. Proceeding reboot.\n"); gcontext->reset(); } return; } VbExDebug("Calling VbSelectFirmware()\n"); res = VbSelectFirmware(context->cparams, context->fparams); VbExDebug("VbSelectFirmware() returned 0x%08x\n", res); if (res != VBERROR_SUCCESS) return; }
static int do_vbexport_test_display(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int ret = 0; uint32_t width, height; GoogleBinaryBlockHeader *gbbh; BmpBlockHeader *bmph; int screen = -1; int local = 0; if (argc > 1) { screen = simple_strtoul(argv[1], NULL, 10); if (argc > 2) local = simple_strtoul(argv[2], NULL, 10); } if (VbExDisplayInit(&width, &height)) { VbExDebug("Failed to init display.\n"); return 1; } VbExDebug("The screen dimensions is %ldx%ld.\n", width, height); VbExDebug("Showing screens for localisation %d...\n", local); mdelay(500); if (screen == -1) { ret |= show_screen_and_delay(VB_SCREEN_BLANK); ret |= show_screen_and_delay(VB_SCREEN_DEVELOPER_WARNING); ret |= show_screen_and_delay(VB_SCREEN_DEVELOPER_EGG); ret |= show_screen_and_delay(VB_SCREEN_RECOVERY_REMOVE); ret |= show_screen_and_delay(VB_SCREEN_RECOVERY_INSERT); ret |= show_screen_and_delay(VB_SCREEN_RECOVERY_NO_GOOD); ret |= show_screen_and_delay(VB_SCREEN_WAIT); } gbbh = (GoogleBinaryBlockHeader *)read_gbb_from_firmware(); if (gbbh) { bmph = (BmpBlockHeader *)((uint8_t *)gbbh + gbbh->bmpfv_offset); VbExDebug("Showing images...\n"); if (screen != -1) { ret |= show_images_and_delay(bmph, local, screen); } else { for (screen = 0; screen < MAX_VALID_SCREEN_INDEX; screen++) ret |= show_images_and_delay(bmph, local, screen); } } else { ret = 1; } VbExDebug("Showing debug info...\n"); ret |= VbExDisplayDebugInfo("Hello!\n" "This is a debug message.\n" "Bye Bye!\n"); return ret; }
static int do_vbexport_test_diskinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int ret = 0; VbExDebug("Detecting all fixed disks...\n"); ret |= do_vbexport_test_diskinfo_flags(VB_DISK_FLAG_FIXED); VbExDebug("\nDetecting all removable disks...\n"); ret |= do_vbexport_test_diskinfo_flags(VB_DISK_FLAG_REMOVABLE); return ret; }
static int do_vbexport_test_key(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int ret = 0; uint32_t c = 0; VbExDebug("Press any key for test. Press Ctrl-C to exit...\n"); while (c != KEY_CTRL_C) { c = VbExKeyboardRead(); if (c) VbExDebug("Key pressed: 0x%02x\n", c); } return ret; }
/** * need comment here */ static int show_images_and_delay(BmpBlockHeader *bmph, int local, int index) { int i; ScreenLayout *screen; ImageInfo *image; screen = (ScreenLayout *)(bmph + 1); screen += local * bmph->number_of_screenlayouts; screen += index; for (i = 0; i < MAX_IMAGE_IN_LAYOUT && screen->images[i].image_info_offset; i++) { image = (ImageInfo *)((uint8_t *)bmph + screen->images[i].image_info_offset); if (show_image(image, screen->images[i].x, screen->images[i].y)) goto bad; } VbExSleepMs(1000); return 0; bad: VbExDebug("Failed to display image, screen=%lu, image=%d!\n", index, i); return 1; }
static int do_vbexport_test_isshutdown(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { VbExDebug("Shutdown requested? %s\n", VbExIsShutdownRequested() ? "Yes" : "No"); return 0; }
static int do_vbexport_test_beep(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int ret = 0; VbExDebug("Performing the beep tests...\n"); ret |= do_vbexport_test_sleep_time(&beep_handler, 500); return ret; }
static int show_screen_and_delay(uint32_t screen_type) { if (VbExDisplayScreen(screen_type)) { VbExDebug("Failed to show a screen.\n"); return 1; } VbExSleepMs(1000); return 0; }
static uint8_t *read_gbb_from_firmware(void) { void *fdt_ptr = (void *)gd->fdt_blob; firmware_storage_t file; struct twostop_fmap fmap; void *gbb; size_t gbb_size; #ifndef CONFIG_HARDWARE_MAPPED_SPI gbb = cros_fdtdec_alloc_region(gd->fdt_blob, "google-binary-block", &gbb_size); if (!gbb) { VbExDebug("Failed to find gbb region!\n"); return NULL; } #endif if (cros_fdtdec_flashmap(fdt_ptr, &fmap)) { VbExDebug("Failed to load fmap config from fdt!\n"); return NULL; } /* Open firmware storage device. */ if (firmware_storage_open_spi(&file)) { VbExDebug("Failed to open firmware device!\n"); return NULL; } #ifdef CONFIG_HARDWARE_MAPPED_SPI { void *gbbp; if (gbb_init(&gbbp, &file, fmap.readonly.gbb.offset, 0)) { VbExDebug("Failed to read GBB!\n"); return NULL; } gbb = gbbp; gbb_size = fmap.readonly.gbb.length; } #else if (gbb_init(gbb, &file, fmap.readonly.gbb.offset, gbb_size)) { VbExDebug("Failed to read GBB!\n"); return NULL; } #endif if (gbb_read_bmp_block(gbb, &file, fmap.readonly.gbb.offset, gbb_size)) { VbExDebug("Failed to load BMP Block in GBB!\n"); return NULL; } if (file.close(&file)) { VbExDebug("Failed to close firmware device!\n"); } return gbb; }
static void vboot_wrapper(void *arg) { int i; VbError_t res; const struct components *components; struct vboot_context *context; context = arg; gcontext = context; VbExDebug("Calling VbInit()\n"); res = VbInit(context->cparams, &context->handoff->init_params); VbExDebug("VbInit() returned 0x%08x\n", res); if (res != VBERROR_SUCCESS) return; VbExDebug("Calling VbSelectFirmware()\n"); res = VbSelectFirmware(context->cparams, context->fparams); VbExDebug("VbSelectFirmware() returned 0x%08x\n", res); if (res != VBERROR_SUCCESS) return; /* Fix up the handoff structure. */ context->handoff->selected_firmware = context->fparams->selected_firmware; /* Parse out the components for downstream consumption. */ if (context->handoff->selected_firmware == VB_SELECT_FIRMWARE_A) components = (void *)context->fw_a; else if (context->handoff->selected_firmware == VB_SELECT_FIRMWARE_B) components = (void *)context->fw_b; else return; for (i = 0; i < MAX_PARSED_FW_COMPONENTS; i++) { parse_component(components, i, &context->handoff->components[i]); } }
static int do_vbexport_test_nvclear(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { uint8_t zero_buf[VBNV_BLOCK_SIZE] = {0}; if (VbExNvStorageWrite(zero_buf)) { VbExDebug("Failed to write nvstorage.\n"); return 1; } return 0; }
static int do_vbexport_test_nvrw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int ret = 0; uint8_t original_buf[VBNV_BLOCK_SIZE]; uint8_t target_buf[VBNV_BLOCK_SIZE]; uint8_t verify_buf[VBNV_BLOCK_SIZE]; int i; for (i = 0; i < VBNV_BLOCK_SIZE; i++) { target_buf[i] = (0x27 + i) % 0x100; } if (VbExNvStorageRead(original_buf)) { VbExDebug("Failed to read nvstorage.\n"); return 1; } if (VbExNvStorageWrite(target_buf)) { VbExDebug("Failed to write nvstorage.\n"); ret = 1; } else { /* Read back and verify the data. */ VbExNvStorageRead(verify_buf); if (memcmp(target_buf, verify_buf, VBNV_BLOCK_SIZE) != 0) { VbExDebug("Verify failed. The target data wrote " "wrong.\n"); ret = 1; } } /* Write the original data back. */ VbExNvStorageWrite(original_buf); if (ret == 0) VbExDebug("Read and write nvstorage test SUCCESS.\n"); return ret; }
static int do_vbexport_test_sleep_time(sleep_handler_t handler, uint32_t msec) { uint32_t start, end, delta, expected; VbExDebug("System is going to sleep for %lu ms...\n", msec); start = VbExGetTimer(); (*handler)(msec); end = VbExGetTimer(); delta = end - start; VbExDebug("From tick %lu to %lu (delta: %lu)", start, end, delta); expected = msec * CONFIG_SYS_HZ; /* The sleeping time should be accurate to within 10%. */ if (delta > expected + expected / 10) { VbExDebug("\nSleep too long: expected %lu but actaully %lu!\n", expected, delta); return 1; } else if (delta < expected - expected / 10) { VbExDebug("\nSleep too short: expected %lu but actaully %lu!\n", expected, delta); return 1; } VbExDebug(" - SUCCESS\n"); return 0; }
static int do_vbexport_test_malloc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int ret = 0; VbExDebug("Performing the malloc/free tests...\n"); ret |= do_vbexport_test_malloc_size(1); ret |= do_vbexport_test_malloc_size(2); ret |= do_vbexport_test_malloc_size(4); ret |= do_vbexport_test_malloc_size(8); ret |= do_vbexport_test_malloc_size(32); ret |= do_vbexport_test_malloc_size(1024); ret |= do_vbexport_test_malloc_size(4 * 1024); ret |= do_vbexport_test_malloc_size(32 * 1024); ret |= do_vbexport_test_malloc_size(1 * 1024 * 1024); ret |= do_vbexport_test_malloc_size(12345); ret |= do_vbexport_test_malloc_size(13579); return ret; }
static int do_vbexport_test_all(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int ret = 0; ret |= do_vbexport_test_debug(cmdtp, flag, argc, argv); ret |= do_vbexport_test_malloc(cmdtp, flag, argc, argv); ret |= do_vbexport_test_sleep(cmdtp, flag, argc, argv); ret |= do_vbexport_test_beep(cmdtp, flag, argc, argv); ret |= do_vbexport_test_diskinfo(cmdtp, flag, argc, argv); ret |= do_vbexport_test_diskrw(cmdtp, flag, argc, argv); ret |= do_vbexport_test_nvrw(cmdtp, flag, argc, argv); ret |= do_vbexport_test_key(cmdtp, flag, argc, argv); ret |= do_vbexport_test_display(cmdtp, flag, argc, argv); ret |= do_vbexport_test_isshutdown(cmdtp, flag, argc, argv); if (!ret) VbExDebug("All tests passed!\n"); return ret; }
VbError_t VbExRegionRead(VbCommonParams *cparams, enum vb_firmware_region region, uint32_t offset, uint32_t size, void *buf) { struct vboot_context *ctx; VbExDebug("VbExRegionRead: offset=%x size=%x, buf=%p\n", offset, size, buf); ctx = cparams->caller_context; if (region == VB_REGION_GBB) { if (offset + size > cparams->gbb_size) return VBERROR_REGION_READ_INVALID; offset += ctx->gbb.offset_addr; if (ctx->get_region(offset, size, buf) == NULL) return VBERROR_REGION_READ_INVALID; return VBERROR_SUCCESS; } return VBERROR_UNSUPPORTED_REGION; }
void *VbExMalloc(size_t size) { void *ptr; if (heap_current == NULL) { heap_current = &_heap[0]; heap_size = &_eheap[0] - &_heap[0]; VbExDebug("vboot heap: %p 0x%08x bytes\n", heap_current, heap_size); } if (heap_size < size) { VbExError("vboot heap request cannot be fulfilled. " "0x%08x available, 0x%08x requested\n", heap_size, size); } ptr = heap_current; heap_size -= size; heap_current += size; return ptr; }
static int do_vbexport_test_image(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { uint32_t width, height; GoogleBinaryBlockHeader *gbbh; BmpBlockHeader *bmph; ScreenLayout *screens; int snum, locale = 0; if (argc > 1) locale = simple_strtoul(argv[1], NULL, 10); if (VbExDisplayInit(&width, &height)) { VbExDebug("Failed to init display.\n"); return 1; } gbbh = (GoogleBinaryBlockHeader *)read_gbb_from_firmware(); if (!gbbh) { VbExDebug("Cannot read GBB\n"); return 1; } bmph = (BmpBlockHeader *)((uint8_t *)gbbh + gbbh->bmpfv_offset); screens = (ScreenLayout *)(bmph + 1); VbExDebug("Total screen layouts: %d\n", bmph->number_of_screenlayouts); VbExDebug("Total localizations: %d\n", bmph->number_of_localizations); VbExDebug("Total images: %d\n", bmph->number_of_imageinfos); VbExDebug("bmpfv_offset=%#x, size=%#x\n", gbbh->bmpfv_offset, gbbh->bmpfv_size); if (locale >= bmph->number_of_localizations) { VbExDebug("Selected localization is out of range\n"); return 1; } /* Select the correct block */ screens += locale * bmph->number_of_screenlayouts; for (snum = 0; snum < bmph->number_of_screenlayouts; snum++) { ScreenLayout *screen = &screens[snum]; ImageInfo *image; int inum; VbExDebug("Screen: %d\n", snum); for (inum = 0; inum < MAX_IMAGE_IN_LAYOUT; inum++) { if (!screen->images[inum].image_info_offset) break; image = (ImageInfo *)((uint8_t *)bmph + screen->images[inum].image_info_offset); VbExDebug(" Image: %d at %d, %d: offset=%#x, " "size=%#x, end=%#x\n", inum, screen->images[inum].x, screen->images[inum].y, gbbh->bmpfv_offset + screen->images[inum].image_info_offset, image->compressed_size, gbbh->bmpfv_offset + screen->images[inum].image_info_offset + image->compressed_size); show_image(image, screen->images[inum].x, screen->images[inum].y); } mdelay(500); } return 0; }
static int do_vbexport_test_diskrw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int ret = 0; VbDiskInfo *disk_info; VbExDiskHandle_t handle; uint32_t disk_count, test_lba_count, buf_byte_count, i; uint8_t *original_buf, *target_buf, *verify_buf; uint64_t t0, t1; switch (argc) { case 1: /* if no argument given, use the default lba count */ test_lba_count = DEFAULT_TEST_LBA_COUNT; break; case 2: /* use argument */ test_lba_count = simple_strtoul(argv[1], NULL, 10); if (!test_lba_count) { VbExDebug("The first argument is not a number!\n"); return cmd_usage(cmdtp); } break; default: return cmd_usage(cmdtp); } /* We perform read/write operations on the first internal disk. */ if (VbExDiskGetInfo(&disk_info, &disk_count, VB_DISK_FLAG_FIXED) || disk_count == 0) { VbExDebug("No internal disk found!\n"); return 1; } handle = disk_info[0].handle; buf_byte_count = disk_info[0].bytes_per_lba * test_lba_count; VbExDiskFreeInfo(disk_info, handle); /* Allocate the buffer and fill the target test pattern. */ original_buf = VbExMalloc(buf_byte_count); target_buf = VbExMalloc(buf_byte_count); verify_buf = VbExMalloc(buf_byte_count); /* Fill the target test pattern. */ for (i = 0; i < buf_byte_count; i++) target_buf[i] = i & 0xff; t0 = VbExGetTimer(); if (VbExDiskRead(handle, TEST_LBA_START, test_lba_count, original_buf)) { VbExDebug("Failed to read disk.\n"); goto out; } t1 = VbExGetTimer(); VbExDebug("test_diskrw: disk_read, lba_count: %u, time: %llu\n", test_lba_count, t1 - t0); t0 = VbExGetTimer(); ret = VbExDiskWrite(handle, TEST_LBA_START, test_lba_count, target_buf); t1 = VbExGetTimer(); VbExDebug("test_diskrw: disk_write, lba_count: %u, time: %llu\n", test_lba_count, t1 - t0); if (ret) { VbExDebug("Failed to write disk.\n"); ret = 1; } else { /* Read back and verify the data. */ VbExDiskRead(handle, TEST_LBA_START, test_lba_count, verify_buf); if (memcmp(target_buf, verify_buf, buf_byte_count) != 0) { VbExDebug("Verify failed. The target data wrote " "wrong.\n"); ret = 1; } } /* Write the original data back. */ if (VbExDiskWrite(handle, TEST_LBA_START, test_lba_count, original_buf)) { VbExDebug("Failed to write the original data back. The disk " "may now be corrupt.\n"); } out: VbExDiskFreeInfo(disk_info, NULL); VbExFree(original_buf); VbExFree(target_buf); VbExFree(verify_buf); if (ret == 0) VbExDebug("Read and write disk test SUCCESS.\n"); return ret; }
static int do_vbexport_test_debug(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { const char c = 'K'; const char s[] = "Hello! It's \"Chrome OS\"."; const int16_t hd = -22222; const uint16_t hu = 44444; const int32_t ld = -1111111111L; const uint32_t lu = 2222222222UL; const int64_t lld = -8888888888888888888LL; const uint64_t llu = 11111111111111111111ULL; VbExDebug("The \"Expect\" and \"Actual\" should be the same...\n"); VbExDebug("Expect: K 75 Hello! It's \"Chrome OS\".\n"); VbExDebug("Actual: %c %d %s\n", c, c, s); VbExDebug("Expect: -22222 0xa932\n"); VbExDebug("Actual: %hd 0x%hx\n", hd, hd); VbExDebug("Expect: 44444 0xad9c\n"); VbExDebug("Actual: %hu 0x%hx\n", hu, hu); VbExDebug("Expect: -1111111111 0xbdc5ca39\n"); VbExDebug("Actual: %ld 0x%lx\n", ld, ld); VbExDebug("Expect: 2222222222 0x84746b8e\n"); VbExDebug("Actual: %lu 0x%lx\n", lu, lu); VbExDebug("Expect: -8888888888888888888 0x84a452a6a1dc71c8\n"); VbExDebug("Actual: %lld 0x%llx\n", lld, lld); VbExDebug("Expect: 11111111111111111111 0x9a3298afb5ac71c7\n"); VbExDebug("Actual: %llu 0x%llx\n", llu, llu); return 0; }
static uint32_t twostop_main_firmware(struct twostop_fmap *fmap, void *gbb, crossystem_data_t *cdata, void *vb_shared_data) { VbError_t err; VbSelectAndLoadKernelParams kparams; VbCommonParams cparams; size_t size = 0; #ifdef CONFIG_BOOTSTAGE_STASH bootstage_unstash((void *)CONFIG_BOOTSTAGE_STASH, CONFIG_BOOTSTAGE_STASH_SIZE); #endif bootstage_mark_name(BOOTSTAGE_VBOOT_TWOSTOP_MAIN_FIRMWARE, "twostop_main_firmware"); if (twostop_init_cparams(fmap, gbb, vb_shared_data, &cparams)) { VBDEBUG("failed to init cparams\n"); return TWOSTOP_SELECT_ERROR; } /* * Note that in case "kernel" is not found in the device tree, the * "size" value is going to remain unchanged. */ kparams.kernel_buffer = cros_fdtdec_alloc_region(gd->fdt_blob, "kernel", &size); kparams.kernel_buffer_size = size; VBDEBUG("kparams:\n"); VBDEBUG("- kernel_buffer: : %p\n", kparams.kernel_buffer); VBDEBUG("- kernel_buffer_size: : %08x\n", kparams.kernel_buffer_size); #ifdef CONFIG_EXYNOS_DISPLAYPORT /* * Make sure the LCD is up before we load the kernel. Partly this * is because VbSelectAndLoadKernel may do a software sync. */ exynos_lcd_check_next_stage(gd->fdt_blob, 1); #endif if ((err = VbSelectAndLoadKernel(&cparams, &kparams))) { VBDEBUG("VbSelectAndLoadKernel: %d\n", err); switch (err) { case VBERROR_SHUTDOWN_REQUESTED: return TWOSTOP_SELECT_POWER_OFF; case VBERROR_BIOS_SHELL_REQUESTED: return TWOSTOP_SELECT_COMMAND_LINE; case VBERROR_EC_REBOOT_TO_RO_REQUIRED: request_ec_reboot_to_ro(); return TWOSTOP_SELECT_POWER_OFF; } return TWOSTOP_SELECT_ERROR; } VBDEBUG("kparams:\n"); VBDEBUG("- kernel_buffer: : %p\n", kparams.kernel_buffer); VBDEBUG("- kernel_buffer_size: : %08x\n", kparams.kernel_buffer_size); VBDEBUG("- disk_handle: : %p\n", kparams.disk_handle); VBDEBUG("- partition_number: : %08x\n", kparams.partition_number); VBDEBUG("- bootloader_address: : %08llx\n", kparams.bootloader_address); VBDEBUG("- bootloader_size: : %08x\n", kparams.bootloader_size); VBDEBUG("- partition_guid: :"); #ifdef VBOOT_DEBUG int i; for (i = 0; i < 16; i++) VbExDebug(" %02x", kparams.partition_guid[i]); VbExDebug("\n"); #endif /* VBOOT_DEBUG */ /* EC might jump between RO and RW during software sync. We need to * update active EC copy in cdata. */ set_active_ec_firmware(cdata); crossystem_data_dump(cdata); #if defined(CONFIG_SANDBOX) return TWOSTOP_SELECT_COMMAND_LINE; #else boot_kernel(&kparams, cdata); /* It is an error if boot_kenel returns */ return TWOSTOP_SELECT_ERROR; #endif }