/* * Print out the contents of a buffer, if debug is enabled. Skip registers * other than FIFO, unless debug_level_ is 2. */ static void trace_dump(const char *prefix, uint32_t reg, size_t bytes, const uint8_t *buffer, int force) { static char prev_prefix CAR_GLOBAL; static unsigned prev_reg CAR_GLOBAL; static int current_char CAR_GLOBAL; const int BYTES_PER_LINE = 32; int *current_char_ptr = car_get_var_ptr(¤t_char); if (!force) { if (!debug_level_) return; if ((debug_level_ < 2) && (reg != TPM_DATA_FIFO_REG)) return; } /* * Do not print register address again if the last dump print was for * that register. */ if ((car_get_var(prev_prefix) != *prefix) || (car_get_var(prev_reg) != reg)) { car_set_var(prev_prefix, *prefix); car_set_var(prev_reg, reg); printk(BIOS_DEBUG, "\n%s %2.2x:", prefix, reg); *current_char_ptr = 0; } if ((reg != TPM_DATA_FIFO_REG) && (bytes == 4)) { /* * This must be a regular register address, print the 32 bit * value. */ printk(BIOS_DEBUG, " %8.8x", *(const uint32_t *)buffer); } else { int i; /* * Data read from or written to FIFO or not in 4 byte * quantiites is printed byte at a time. */ for (i = 0; i < bytes; i++) { if (*current_char_ptr && !(*current_char_ptr % BYTES_PER_LINE)) { printk(BIOS_DEBUG, "\n "); *current_char_ptr = 0; } (*current_char_ptr)++; printk(BIOS_DEBUG, " %2.2x", buffer[i]); } } }
int tis_open(void) { if (car_get_var(tpm_is_open)) { printk(BIOS_ERR, "tis_open() called twice.\n"); return -1; } return 0; }
static inline int get_log_level(void) { if (car_get_var(console_inited) == 0) return -1; if (CONSOLE_LEVEL_CONST) return get_console_loglevel(); return console_loglevel; }
const struct spi_flash *boot_device_spi_flash(void) { boot_device_rw_init(); if (car_get_var(sfg_init_done) != true) return NULL; return car_get_var_ptr(&sfg); }
const struct region_device *boot_device_rw(void) { /* Probe for the SPI flash device if not already done. */ boot_device_rw_init(); if (car_get_var(sfg) == NULL) return NULL; return &spi_rw; }
__weak int tis_plat_irq_status(void) { static int warning_displayed CAR_GLOBAL; if (!car_get_var(warning_displayed)) { printk(BIOS_WARNING, "WARNING: tis_plat_irq_status() not implemented, wasting 10ms to wait on Cr50!\n"); car_set_var(warning_displayed, 1); } mdelay(10); return 1; }
static ssize_t spi_eraseat(const struct region_device *rd, size_t offset, size_t size) { struct spi_flash *sf = car_get_var(sfg); if (sf == NULL) return -1; if (spi_flash_erase(sf, offset, size)) return -1; return size; }
static void boot_device_rw_init(void) { const int bus = CONFIG_BOOT_DEVICE_SPI_FLASH_BUS; const int cs = 0; if (car_get_var(sfg) != NULL) return; /* Ensure any necessary setup is performed by the drivers. */ spi_init(); car_set_var(sfg, spi_flash_probe(bus, cs)); }
int tis_close(void) { if (car_get_var(tpm_is_open)) { /* * Do we need to do something here, like waiting for a * transaction to stop? */ car_set_var(tpm_is_open, 0); } return 0; }
static ssize_t spi_writeat(const struct region_device *rd, const void *b, size_t offset, size_t size) { struct spi_flash *sf = car_get_var(sfg); if (sf == NULL) return -1; if (spi_flash_write(sf, offset, size, b)) return -1; return size; }
static void boot_device_rw_init(void) { const int bus = CONFIG_BOOT_DEVICE_SPI_FLASH_BUS; const int cs = 0; if (car_get_var(sfg_init_done) == true) return; /* Ensure any necessary setup is performed by the drivers. */ spi_init(); if (!spi_flash_probe(bus, cs, car_get_var_ptr(&sfg))) car_set_var(sfg_init_done, true); }
static int vboot_logic_executed(void) { /* If this stage is supposed to run the vboot logic ensure it has been * executed. */ if (verification_should_run() && car_get_var(vboot_executed)) return 1; /* If this stage is supposed to load verstage and verstage is returning * back to the calling stage check that it has been executed. */ if (verstage_should_load() && IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE)) if (car_get_var(vboot_executed)) return 1; /* Handle all other stages post vboot execution. */ if (!ENV_BOOTBLOCK) { if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK)) return 1; if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE) && !ENV_ROMSTAGE) return 1; } return 0; }
int vb2_logic_executed(void) { /* If we are in a stage that would load the verstage or execute the vboot logic directly, we store the answer in a global. */ if (verstage_should_load() || verification_should_run()) return car_get_var(vboot_executed); if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK)) { /* All other stages are "after the bootblock" */ return !ENV_BOOTBLOCK; } else if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE)) { /* Post-RAM stages are "after the romstage" */ #ifdef __PRE_RAM__ return 0; #else return 1; #endif } else { die("impossible!"); } }
int tpm_marshal_command(TPM_CC command, void *tpm_command_body, struct obuf *ob) { struct obuf ob_hdr; const size_t hdr_sz = sizeof(uint16_t) + 2 * sizeof(uint32_t); int rc = 0; car_set_var(tpm_tag, TPM_ST_NO_SESSIONS); if (obuf_splice_current(ob, &ob_hdr, hdr_sz) < 0) return -1; /* Write TPM command header with placeholder field values. */ rc |= obuf_write_be16(ob, 0); rc |= obuf_write_be32(ob, 0); rc |= obuf_write_be32(ob, command); if (rc != 0) return rc; switch (command) { case TPM2_Startup: rc |= marshal_startup(ob, tpm_command_body); break; case TPM2_Shutdown: rc |= marshal_shutdown(ob, tpm_command_body); break; case TPM2_GetCapability: rc |= marshal_get_capability(ob, tpm_command_body); break; case TPM2_NV_Read: rc |= marshal_nv_read(ob, tpm_command_body); break; case TPM2_NV_DefineSpace: rc |= marshal_nv_define_space(ob, tpm_command_body); break; case TPM2_NV_Write: rc |= marshal_nv_write(ob, tpm_command_body); break; case TPM2_NV_WriteLock: rc |= marshal_nv_write_lock(ob, tpm_command_body); break; case TPM2_SelfTest: rc |= marshal_selftest(ob, tpm_command_body); break; case TPM2_Hierarchy_Control: rc |= marshal_hierarchy_control(ob, tpm_command_body); break; case TPM2_Clear: rc |= marshal_clear(ob); break; case TPM2_PCR_Extend: rc |= marshal_pcr_extend(ob, tpm_command_body); break; case TPM2_CR50_VENDOR_COMMAND: rc |= marshal_cr50_vendor_command(ob, tpm_command_body); break; default: printk(BIOS_INFO, "%s:%d:Request to marshal unsupported command %#x\n", __FILE__, __LINE__, command); rc = -1; } if (rc != 0) return rc; /* Fix up the command header with known values. */ rc |= obuf_write_be16(&ob_hdr, car_get_var(tpm_tag)); rc |= obuf_write_be32(&ob_hdr, obuf_nr_written(ob)); return rc; }
void init_timer(void) { if (!car_get_var(clocks_per_usec)) car_set_var(clocks_per_usec, calibrate_tsc()); }
static int oxpcie_uart_active(void) { return (car_get_var(oxpcie_present)); }
static inline u32 get_timer_fsb(void) { return car_get_var(g_timer_fsb); }
static inline unsigned long get_clocks_per_usec(void) { init_timer(); return car_get_var(clocks_per_usec); }
void tpm2_get_info(struct tpm2_info *info) { *info = car_get_var(g_tpm_info); }
/* * Each TPM2 SPI transaction starts the same: CS is asserted, the 4 byte * header is sent to the TPM, the master waits til TPM is ready to continue. * * Returns 1 on success, 0 on failure (TPM SPI flow control timeout.) */ static int start_transaction(int read_write, size_t bytes, unsigned addr) { spi_frame_header header; uint8_t byte; int i; struct stopwatch sw; static int tpm_sync_needed CAR_GLOBAL; static struct stopwatch wake_up_sw CAR_GLOBAL; struct spi_slave *spi_slave = car_get_var_ptr(&g_spi_slave); /* * First Cr50 access in each coreboot stage where TPM is used will be * prepended by a wake up pulse on the CS line. */ int wakeup_needed = 1; /* Wait for TPM to finish previous transaction if needed */ if (car_get_var(tpm_sync_needed)) { tpm_sync(); /* * During the first invocation of this function on each stage * this if () clause code does not run (as tpm_sync_needed * value is zero), during all following invocations the * stopwatch below is guaranteed to be started. */ if (!stopwatch_expired(car_get_var_ptr(&wake_up_sw))) wakeup_needed = 0; } else { car_set_var(tpm_sync_needed, 1); } if (wakeup_needed) { /* Just in case Cr50 is asleep. */ spi_claim_bus(spi_slave); udelay(1); spi_release_bus(spi_slave); udelay(100); } /* * The Cr50 on H1 does not go to sleep for 1 second after any * SPI slave activity, let's be conservative and limit the * window to 900 ms. */ stopwatch_init_msecs_expire(car_get_var_ptr(&wake_up_sw), 900); /* * The first byte of the frame header encodes the transaction type * (read or write) and transfer size (set to lentgh - 1), limited to * 64 bytes. */ header.body[0] = (read_write ? 0x80 : 0) | 0x40 | (bytes - 1); /* The rest of the frame header is the TPM register address. */ for (i = 0; i < 3; i++) header.body[i + 1] = (addr >> (8 * (2 - i))) & 0xff; /* CS assert wakes up the slave. */ spi_claim_bus(spi_slave); /* * The TCG TPM over SPI specification introduces the notion of SPI * flow control (Section "6.4.5 Flow Control"). * * Again, the slave (TPM device) expects each transaction to start * with a 4 byte header trasmitted by master. The header indicates if * the master needs to read or write a register, and the register * address. * * If the slave needs to stall the transaction (for instance it is not * ready to send the register value to the master), it sets the MOSI * line to 0 during the last clock of the 4 byte header. In this case * the master is supposed to start polling the SPI bus, one byte at * time, until the last bit in the received byte (transferred during * the last clock of the byte) is set to 1. * * Due to some SPI controllers' shortcomings (Rockchip comes to * mind...) we trasmit the 4 byte header without checking the byte * transmitted by the TPM during the transaction's last byte. * * We know that cr50 is guaranteed to set the flow control bit to 0 * during the header transfer, but real TPM2 might be fast enough not * to require to stall the master, this would present an issue. * crosbug.com/p/52132 has been opened to track this. */ spi_xfer(spi_slave, header.body, sizeof(header.body), NULL, 0); /* * Now poll the bus until TPM removes the stall bit. Give it up to 100 * ms to sort it out - it could be saving stuff in nvram at some * point. */ stopwatch_init_msecs_expire(&sw, 100); do { if (stopwatch_expired(&sw)) { printk(BIOS_ERR, "TPM flow control failure\n"); spi_release_bus(spi_slave); return 0; } spi_xfer(spi_slave, NULL, 0, &byte, 1); } while (!(byte & 1)); return 1; }
asmlinkage void car_stage_entry(void) { struct postcar_frame pcf; uintptr_t top_of_ram; bool s3wake; struct chipset_power_state *ps = car_get_var_ptr(&power_state); void *smm_base; size_t smm_size, var_size; const void *new_var_data; uintptr_t tseg_base; timestamp_add_now(TS_START_ROMSTAGE); soc_early_romstage_init(); disable_watchdog(); console_init(); s3wake = fill_power_state(ps) == ACPI_S3; fsp_memory_init(s3wake); if (punit_init()) set_max_freq(); else printk(BIOS_DEBUG, "Punit failed to initialize properly\n"); /* Stash variable MRC data and let cache system update it later */ new_var_data = fsp_find_extension_hob_by_guid(hob_variable_guid, &var_size); if (new_var_data) mrc_cache_stash_vardata(new_var_data, var_size, car_get_var(fsp_version)); else printk(BIOS_ERR, "Failed to determine variable data\n"); if (postcar_frame_init(&pcf, 1*KiB)) die("Unable to initialize postcar frame.\n"); mainboard_save_dimm_info(); /* * We need to make sure ramstage will be run cached. At this point exact * location of ramstage in cbmem is not known. Instruct postcar to cache * 16 megs under cbmem top which is a safe bet to cover ramstage. */ top_of_ram = (uintptr_t) cbmem_top(); /* cbmem_top() needs to be at least 16 MiB aligned */ assert(ALIGN_DOWN(top_of_ram, 16*MiB) == top_of_ram); postcar_frame_add_mtrr(&pcf, top_of_ram - 16*MiB, 16*MiB, MTRR_TYPE_WRBACK); /* Cache the memory-mapped boot media. */ if (IS_ENABLED(CONFIG_BOOT_DEVICE_MEMORY_MAPPED)) postcar_frame_add_mtrr(&pcf, -CONFIG_ROM_SIZE, CONFIG_ROM_SIZE, MTRR_TYPE_WRPROT); /* * Cache the TSEG region at the top of ram. This region is * not restricted to SMM mode until SMM has been relocated. * By setting the region to cacheable it provides faster access * when relocating the SMM handler as well as using the TSEG * region for other purposes. */ smm_region(&smm_base, &smm_size); tseg_base = (uintptr_t)smm_base; postcar_frame_add_mtrr(&pcf, tseg_base, smm_size, MTRR_TYPE_WRBACK); run_postcar_phase(&pcf); }
const struct spi_flash *boot_device_spi_flash(void) { boot_device_rw_init(); return car_get_var(sfg); }
void qemu_debugcon_tx_byte(unsigned char data) { if (car_get_var(qemu_debugcon_detected) != 0) outb(data, CONFIG_CONSOLE_QEMU_DEBUGCON_PORT); }