int cros_cboot_twostop_read_bmp_block(void) { /* Yet another use of this evil #define */ #ifndef CONFIG_HARDWARE_MAPPED_SPI firmware_storage_t file; int ret; if (have_read_gbb_bmp_block) return 0; if (!fmap.readonly.fmap.length && cros_fdtdec_flashmap(gd->fdt_blob, &fmap)) { VBDEBUG("failed to decode fmap\n"); return -1; } if (firmware_storage_open_spi(&file)) { VBDEBUG("failed to open firmware storage\n"); return -1; } ret = gbb_read_bmp_block(static_gbb, &file, fmap.readonly.gbb.offset, fmap.readonly.gbb.length); file.close(&file); if (ret) return -1; have_read_gbb_bmp_block = 1; #endif /* CONFIG_HARDWARE_MAPPED_SPI */ return 0; }
int vboot_flag_dump(enum vboot_flag_id id, struct vboot_flag_details *details) { #ifdef VBOOT_DEBUG struct vboot_flag_details local_details; if (id < 0 || id >= VBOOT_FLAG_MAX_FLAGS) { VBDEBUG("id out of range: %d\n", id); return -1; } if (details == NULL) { if (vboot_flag_fetch(id, &local_details)) { VBDEBUG("failed to get vboot_flag details of %s\n", vboot_flag_node_name(id)); return -1; } details = &local_details; } VBDEBUG("%-24s: port=%3d, active_high=%d, value=%d\n", vboot_flag_node_name(id), details->port, details->active_high, details->value); #endif return 0; }
static int do_vboot_twostop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { uint32_t selection; int ro_firmware; bootstage_mark_name(BOOTSTAGE_VBOOT_TWOSTOP, "do_vboot_twostop"); /* * Empty keyboard buffer before boot. In case EC did not clear its * buffer between power cycles, this prevents vboot of current power * cycle being affected by keystrokes of previous power cycle. */ while (tstc()) getc(); if (cros_init()) { VBDEBUG("fail to init cros library\n"); goto on_error; } /* * TODO: We should clear screen later if we load graphics optionally. * In normal mode, we don't need to load graphics driver and clear * screen. */ display_clear(); /* * A processor reset jumps to the reset entry point (which is the * read-only firmware), otherwise we have entered U-Boot from a * software jump. * * Note: If a read-only firmware is loaded to memory not because of a * processor reset, this instance of read-only firmware should go to the * readwrite firmware code path. */ ro_firmware = is_processor_reset(); VBDEBUG("Starting %s firmware\n", ro_firmware ? "read-only" : "read-write"); if (ro_firmware) selection = twostop_boot(0); else selection = twostop_readwrite_main_firmware(); VBDEBUG("selection of main firmware: %s\n", str_selection(selection)); if (selection == TWOSTOP_SELECT_COMMAND_LINE) return 0; if (selection == TWOSTOP_SELECT_POWER_OFF) power_off(); assert(selection == TWOSTOP_SELECT_ERROR); on_error: cold_reboot(); return 0; }
uint8_t* ReadFile(const char* filename, uint64_t* sizeptr) { FILE* f; uint8_t* buf; uint64_t size; f = fopen(filename, "rb"); if (!f) { VBDEBUG(("Unable to open file %s\n", filename)); return NULL; } fseek(f, 0, SEEK_END); size = ftell(f); rewind(f); buf = malloc(size); if (!buf) { fclose(f); return NULL; } if(1 != fread(buf, size, 1, f)) { VBDEBUG(("Unable to read from file %s\n", filename)); fclose(f); free(buf); return NULL; } fclose(f); if (sizeptr) *sizeptr = size; return buf; }
static int vboot_flag_fetch_sysinfo(enum vboot_flag_id id, struct vboot_flag_context *context, struct vboot_flag_details *details) { const void *blob = gd->fdt_blob; const struct fdt_property *prop; int len, i, p; prop = fdt_get_property(blob, context->node, "google,name", &len); if (!prop) { VBDEBUG("failed to read name of %s\n", vboot_flag_node_name(id)); return -1; } for (i = 0; i < lib_sysinfo.num_gpios; i++) { if (strncmp((char *)lib_sysinfo.gpios[i].name, prop->data, GPIO_MAX_NAME_LENGTH)) continue; /* Entry found */ details->port = lib_sysinfo.gpios[i].port; details->active_high = lib_sysinfo.gpios[i].polarity; p = details->active_high ? 0 : 1; details->value = p ^ lib_sysinfo.gpios[i].value; return 0; } VBDEBUG("failed to find gpio port for %s\n", vboot_flag_node_name(id)); return -1; }
int RestoreNvFromBackup(VbNvContext *vnc) { VbNvContext bvnc; uint32_t value; int i; VBDEBUG(("TPM: %s()\n", __func__)); if (TPM_SUCCESS != RollbackBackupRead(bvnc.raw)) return 1; VbNvSetup(&bvnc); if (bvnc.regenerate_crc) { VBDEBUG(("TPM: Oops, backup is no good.\n")); return 1; } for (i = 0; i < ARRAY_SIZE(backup_params); i++) { VbNvGet(&bvnc, backup_params[i], &value); VbNvSet(vnc, backup_params[i], value); } /* VbNvTeardown(&bvnc); is not needed. We're done with it. */ return 0; }
/* Like TlclSendReceive below, but do not retry if NEEDS_SELFTEST or * DOING_SELFTEST errors are returned. */ static uint32_t tlcl_send_receive_no_retry(const uint8_t* request, uint8_t* response, int max_length) { uint32_t response_length = max_length; uint32_t result; result = tpm_send_receive(request, tpm_command_size(request), response, &response_length); if (0 != result) { /* Communication with TPM failed, so response is garbage */ VBDEBUG("TPM: command 0x%x send/receive failed: 0x%x\n", tpm_command_code(request), result); return result; } /* Otherwise, use the result code from the response */ result = tpm_return_code(response); /* TODO: add paranoia about returned response_length vs. max_length * (and possibly expected length from the response header). See * crosbug.com/17017 */ VBDEBUG("TPM: command 0x%x returned 0x%x\n", tpm_command_code(request), result); return result; }
static uint32_t write_secdata(uint32_t index, const uint8_t *secdata, uint32_t len) { uint8_t sd[32]; uint32_t rv; int attempts = 3; if (len > sizeof(sd)) { VBDEBUG("TPM: %s() - data is too large\n", __func__); return TPM_E_WRITE_FAILURE; } while (attempts--) { rv = safe_write(index, secdata, len); /* Can't write, not gonna try again */ if (rv != TPM_SUCCESS) return rv; /* Read it back to be sure it got the right values. */ rv = tlcl_read(index, sd, len); if (rv == TPM_SUCCESS && memcmp(secdata, sd, len) == 0) return rv; VBDEBUG("TPM: %s() failed. trying again\n", __func__); /* Try writing it again. Maybe it was garbled on the way out. */ } VBDEBUG("TPM: %s() - too many failures, giving up\n", __func__); return TPM_E_CORRUPTED_STATE; }
/* Write-protect portions of the RW flash until the next boot. */ VbError_t VbExProtectFlash(enum VbProtectFlash_t region) { #ifdef CONFIG_CAN_PROTECT_RW_FLASH switch (region) { case VBPROTECT_RW_A: VBDEBUG("VBPROTECT_RW_A => 0x%08x 0x%x\n", fmap.readwrite_a.all.offset, fmap.readwrite_a.all.length); spi_write_protect_region(fmap.readwrite_a.all.offset, fmap.readwrite_a.all.length, 0); break; case VBPROTECT_RW_B: VBDEBUG("VBPROTECT_RW_B => 0x%08x 0x%x\n", fmap.readwrite_b.all.offset, fmap.readwrite_b.all.length); spi_write_protect_region(fmap.readwrite_b.all.offset, fmap.readwrite_b.all.length, 0); break; case VBPROTECT_RW_DEVKEY: VBDEBUG("VBPROTECT_RW_DEVKEY => 0x%08x 0x%x\n", fmap.readwrite_devkey.offset, fmap.readwrite_devkey.length); spi_write_protect_region(fmap.readwrite_devkey.offset, fmap.readwrite_devkey.length, 1); break; default: VBDEBUG("unknown region %d\n", region); return VBERROR_INVALID_PARAMETER; } return VBERROR_SUCCESS; #else VBDEBUG("%s not implemented on this platform\n", __func__); return VBERROR_UNKNOWN; #endif }
int VbSharedDataInit(VbSharedDataHeader *header, uint64_t size) { VBDEBUG(("VbSharedDataInit, %d bytes, header %d bytes\n", (int)size, (int)sizeof(VbSharedDataHeader))); if (size < sizeof(VbSharedDataHeader)) { VBDEBUG(("Not enough data for header.\n")); return VBOOT_SHARED_DATA_INVALID; } if (size < VB_SHARED_DATA_MIN_SIZE) { VBDEBUG(("Shared data buffer too small.\n")); return VBOOT_SHARED_DATA_INVALID; } if (!header) return VBOOT_SHARED_DATA_INVALID; /* Zero the header */ Memset(header, 0, sizeof(VbSharedDataHeader)); /* Initialize fields */ header->magic = VB_SHARED_DATA_MAGIC; header->struct_version = VB_SHARED_DATA_VERSION; header->struct_size = sizeof(VbSharedDataHeader); header->data_size = size; header->data_used = sizeof(VbSharedDataHeader); header->firmware_index = 0xFF; /* Success */ return VBOOT_SUCCESS; }
VbError_t VbUnlockDevice(void) { VBDEBUG(("%s() Enabling dev-mode...\n", __func__)); if (TPM_SUCCESS != SetVirtualDevMode(1)) return VBERROR_TPM_SET_BOOT_MODE_STATE; VBDEBUG(("%s() Mode change will take effect on next reboot.\n", __func__)); return VBERROR_SUCCESS; }
/** * Wrapper around VbExEcProtectRW() which sets recovery reason on error. */ static VbError_t EcProtectRW(int devidx) { int rv = VbExEcProtectRW(devidx); if (rv == VBERROR_EC_REBOOT_TO_RO_REQUIRED) { VBDEBUG(("VbExEcProtectRW() needs reboot\n")); } else if (rv != VBERROR_SUCCESS) { VBDEBUG(("VbExEcProtectRW() returned %d\n", rv)); VbSetRecoveryRequest(VBNV_RECOVERY_EC_PROTECT); } return rv; }
static uint32_t twostop_readwrite_main_firmware(void) { crossystem_data_t *cdata; void *gbb; size_t gbb_size; if (!fmap.readonly.fmap.length && cros_fdtdec_flashmap(gd->fdt_blob, &fmap)) { VBDEBUG("failed to decode fmap\n"); return TWOSTOP_SELECT_ERROR; } dump_fmap(&fmap); #ifdef CONFIG_HARDWARE_MAPPED_SPI gbb = (void *) (fmap.readonly.gbb.offset + fmap.flash_base); #endif if (setup_gbb_and_cdata(&gbb, &gbb_size, &cdata, 1)) return TWOSTOP_SELECT_ERROR; static_gbb = gbb; #ifdef CONFIG_ARM uint8_t ro_nvtype = cdata->board.arm.nonvolatile_context_storage; if (ro_nvtype == NONVOLATILE_STORAGE_NONE) { /* * Default to disk for older RO firmware which does not provide * storage type. */ cdata->board.arm.nonvolatile_context_storage = NONVOLATILE_STORAGE_DISK; } else { /* RW has to use the storage type that RO was using. */ if (nvstorage_set_type(ro_nvtype)) return TWOSTOP_SELECT_ERROR; } #endif /* CONFIG_ARM */ /* * VbSelectAndLoadKernel() assumes the TPM interface has already been * initialized by VbSelectFirmware(). Since we haven't called * VbSelectFirmware() in the readwrite firmware, we need to explicitly * initialize the TPM interface. Note that this only re-initializes the * interface, not the TPM itself. */ if (VbExTpmInit() != TPM_SUCCESS) { VBDEBUG("failed to init tpm interface\n"); return TWOSTOP_SELECT_ERROR; } /* TODO Now, initialize device that bootstub did not initialize */ return twostop_main_firmware(&fmap, gbb, cdata, cdata->vb_shared_data); }
uint64_t VbSharedDataReserve(VbSharedDataHeader *header, uint64_t size) { uint64_t offs = header->data_used; VBDEBUG(("VbSharedDataReserve %d bytes at %d\n", (int)size, (int)offs)); if (!header || size > header->data_size - header->data_used) { VBDEBUG(("VbSharedData buffer out of space.\n")); return 0; /* Not initialized, or not enough space left. */ } header->data_used += size; return offs; }
static void VbTryLegacy(int allowed) { if (!allowed) VBDEBUG(("VbBootDeveloper() - Legacy boot is disabled\n")); else if (0 != RollbackKernelLock(0)) VBDEBUG(("Error locking kernel versions on legacy boot.\n")); else VbExLegacy(); /* will not return if successful */ /* If legacy boot fails, beep and return to calling UI loop. */ VbExBeep(120, 400); VbExSleepMs(120); VbExBeep(120, 400); }
void jump_to_firmware(void (*firmware_entry_point)(void)) { VBDEBUG(PREFIX "jump to firmware %p\n", firmware_entry_point); cleanup_before_linux(); /* should never return! */ firmware_entry_point(); /* FIXME(clchiou) Bring up a sad face as boot has failed */ enable_interrupts(); VBDEBUG(PREFIX "error: firmware returns\n"); while (1); }
static int twostop_init_cparams(struct twostop_fmap *fmap, void *gbb, void *vb_shared_data, VbCommonParams *cparams) { cparams->gbb_data = gbb; cparams->gbb_size = fmap->readonly.gbb.length; #ifdef CONFIG_SYS_COREBOOT cparams->shared_data_blob = &((chromeos_acpi_t *)lib_sysinfo.vdat_addr)->vdat; cparams->shared_data_size = sizeof(((chromeos_acpi_t *)lib_sysinfo.vdat_addr)->vdat); #else cparams->shared_data_blob = vb_shared_data; cparams->shared_data_size = VB_SHARED_DATA_REC_SIZE; #endif #define P(format, field) \ VBDEBUG("- %-20s: " format "\n", #field, cparams->field) VBDEBUG("cparams:\n"); P("%p", gbb_data); P("%08x", gbb_size); P("%p", shared_data_blob); P("%08x", shared_data_size); #undef P return 0; }
static void* MMapFile(const char* filename, size_t *size) { FILE* f; uint8_t* buf; long file_size = 0; f = fopen(filename, "rb"); if (!f) { VBDEBUG(("Unable to open file %s\n", filename)); return NULL; } fseek(f, 0, SEEK_END); file_size = ftell(f); rewind(f); if (file_size <= 0) { fclose(f); return NULL; } *size = (size_t) file_size; /* Uses a host primitive as this is not meant for firmware use. */ buf = mmap(NULL, *size, PROT_READ, MAP_PRIVATE, fileno(f), 0); if (buf == MAP_FAILED) { VbExError("Failed to mmap the file %s\n", filename); fclose(f); return NULL; } fclose(f); return buf; }
VbError_t test_mockable VbBootNormal(VbCommonParams *cparams, LoadKernelParams *p) { /* Boot from fixed disk only */ VBDEBUG(("Entering %s()\n", __func__)); return VbTryLoadKernel(cparams, p, VB_DISK_FLAG_FIXED); }
int WriteFile(const char* filename, const void *data, uint64_t size) { FILE *f = fopen(filename, "wb"); if (!f) { VBDEBUG(("Unable to open file %s\n", filename)); return 1; } if (1 != fwrite(data, size, 1, f)) { VBDEBUG(("Unable to write to file %s\n", filename)); fclose(f); unlink(filename); /* Delete any partial file */ } fclose(f); return 0; }
static int flash_sw_wp_is_enabled(firmware_storage_t *file) { uint8_t yes_it_is = 0; #ifdef CONFIG_SPI_FLASH int r = 0; r = spi_flash_read_sw_wp_status(file->context, &yes_it_is); if (r) { VBDEBUG("spi_flash_read_sw_wp_status() failed: %d\n", r); return 0; } #endif VBDEBUG("flash SW WP is %d\n", yes_it_is); return yes_it_is; }
int VbSharedDataSetKernelKey(VbSharedDataHeader *header, const VbPublicKey *src) { VbPublicKey *kdest = &header->kernel_subkey; VBDEBUG(("Saving kernel subkey to shared data: size %d, algo %d\n", siglen_map[src->algorithm], (int)src->algorithm)); if (!header) return VBOOT_SHARED_DATA_INVALID; /* Attempt to allocate space for key, if it hasn't been allocated yet */ if (!header->kernel_subkey_data_offset) { header->kernel_subkey_data_offset = VbSharedDataReserve(header, src->key_size); if (!header->kernel_subkey_data_offset) return VBOOT_SHARED_DATA_INVALID; header->kernel_subkey_data_size = src->key_size; } /* Copy the kernel sign key blob into the destination buffer */ PublicKeyInit(kdest, (uint8_t *)header + header->kernel_subkey_data_offset, header->kernel_subkey_data_size); return PublicKeyCopy(kdest, src); }
VbError_t nvstorage_write_disk(const uint8_t *buf) { VbDiskInfo *internal_disk; uint8_t *block_buf; if (get_internal_disk(&internal_disk)) return 1; if (get_nvcxt_block_of_disk(internal_disk, &block_buf)) return 1; memcpy(block_buf, buf, VBNV_BLOCK_SIZE); if (VbExDiskWrite(internal_disk->handle, CHROMEOS_VBNVCONTEXT_LBA, 1, block_buf)) { VBDEBUG("Failed to write internal disk!\n"); VbExFree(block_buf); return 1; } VbExFree(block_buf); #ifdef CONFIG_EXYNOS5 /* * XXX(chrome-os-partner:10415): On Exynos, reliable write operations * need write busy time; so add a delay here. In the long run, we * should avoid using eMMC as VbNvContext storage media. */ mdelay(1); #endif return VBERROR_SUCCESS; }
int VbNvSet(VbNvContext *context, VbNvParam param, uint32_t value) { VBDEBUG(("%s(): got_recovery_request_val = %d (0x%x)\n", __FUNCTION__, value, value)); got_recovery_request_val = value; return 0; }
VbError_t VbExDiskGetInfo(VbDiskInfo **infos_ptr, uint32_t *count, uint32_t disk_flags) { int i; int num_disks = 0; VBDEBUG(("My %s\n", __FUNCTION__)); *infos_ptr = mock_disks; for(i = 0; i < MAX_TEST_DISKS; i++) { if (is_nonzero(&t->disks_to_provide[i], sizeof(t->disks_to_provide[i]))) { mock_disks[num_disks].bytes_per_lba = t->disks_to_provide[i].bytes_per_lba; mock_disks[num_disks].lba_count = mock_disks[num_disks].streaming_lba_count = t->disks_to_provide[i].lba_count; mock_disks[num_disks].flags = t->disks_to_provide[i].flags; mock_disks[num_disks].handle = (VbExDiskHandle_t) t->disks_to_provide[i].diskname; VBDEBUG((" mock_disk[%d] %" PRIu64 " %" PRIu64 " 0x%x %s\n", i, mock_disks[num_disks].bytes_per_lba, mock_disks[num_disks].lba_count, mock_disks[num_disks].flags, (mock_disks[num_disks].handle ? (char *)mock_disks[num_disks].handle : "0"))); num_disks++; } else { mock_disks[num_disks].handle = (VbExDiskHandle_t)"INVALID"; } } if (t->disk_count_to_return >= 0) *count = t->disk_count_to_return; else *count = num_disks; VBDEBUG((" *count=%" PRIu32 "\n", *count)); VBDEBUG((" return 0x%x\n", t->diskgetinfo_return_val)); return t->diskgetinfo_return_val; }
uint32_t tlcl_set_deactivated(uint8_t flag) { struct s_tpm_physicalsetdeactivated_cmd cmd; VBDEBUG("TPM: SetDeactivated(%d)\n", flag); memcpy(&cmd, &tpm_physicalsetdeactivated_cmd, sizeof(cmd)); *(cmd.buffer + cmd.deactivated) = flag; return send(cmd.buffer); }
static uint32_t read_space_firmware(struct vb2_context *ctx) { int attempts = 3; while (attempts--) { RETURN_ON_FAILURE(tlcl_read(FIRMWARE_NV_INDEX, ctx->secdata, VB2_SECDATA_SIZE)); if (vb2api_secdata_check(ctx) == VB2_SUCCESS) return TPM_SUCCESS; VBDEBUG("TPM: %s() - bad CRC\n", __func__); } VBDEBUG("TPM: %s() - too many bad CRCs, giving up\n", __func__); return TPM_E_CORRUPTED_STATE; }
VbError_t VbExDiskFreeInfo(VbDiskInfo *infos, VbExDiskHandle_t preserve_handle) { got_load_disk = (const char *)preserve_handle; VBDEBUG(("%s(): got_load_disk = %s\n", __FUNCTION__, got_load_disk ? got_load_disk : "0")); return VBERROR_SUCCESS; }
uint32_t tlcl_continue_self_test(void) { uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; VBDEBUG("TPM: Continue self test\n"); /* Call the No Retry version of SendReceive to avoid recursion. */ return tlcl_send_receive_no_retry(tpm_continueselftest_cmd.buffer, response, sizeof(response)); }
uint32_t tpm_clear_and_reenable(void) { VBDEBUG("TPM: Clear and re-enable\n"); RETURN_ON_FAILURE(tlcl_force_clear()); RETURN_ON_FAILURE(tlcl_set_enable()); RETURN_ON_FAILURE(tlcl_set_deactivated(0)); return TPM_SUCCESS; }