/** * Find PEI executable in coreboot filesystem and execute it. * * @param pei_data: configuration data for UEFI PEI reference code */ void sdram_initialize(struct pei_data *pei_data) { struct sys_info sysinfo; int (*entry) (struct pei_data *pei_data) __attribute__ ((regparm(1))); report_platform_info(); /* Wait for ME to be ready */ intel_early_me_init(); intel_early_me_uma_size(); printk(BIOS_DEBUG, "Starting UEFI PEI System Agent\n"); memset(&sysinfo, 0, sizeof(sysinfo)); sysinfo.boot_path = pei_data->boot_mode; /* * Do not pass MRC data in for recovery mode boot, * Always pass it in for S3 resume. */ if (!vboot_recovery_mode_enabled() || pei_data->boot_mode == 2) prepare_mrc_cache(pei_data); /* If MRC data is not found we cannot continue S3 resume. */ if (pei_data->boot_mode == 2 && !pei_data->mrc_input) { printk(BIOS_DEBUG, "Giving up in sdram_initialize: No MRC data\n"); outb(0x6, 0xcf9); halt(); } /* Pass console handler in pei_data */ pei_data->tx_byte = do_putchar; /* Locate and call UEFI System Agent binary. */ entry = cbfs_boot_map_with_leak("mrc.bin", CBFS_TYPE_MRC, NULL); if (entry) { int rv; rv = entry (pei_data); if (rv) { switch (rv) { case -1: printk(BIOS_ERR, "PEI version mismatch.\n"); break; case -2: printk(BIOS_ERR, "Invalid memory frequency.\n"); break; default: printk(BIOS_ERR, "MRC returned %x.\n", rv); } die("Nonzero MRC return value.\n"); } } else { die("UEFI PEI System Agent not found.\n"); } #if CONFIG_USBDEBUG_IN_ROMSTAGE /* mrc.bin reconfigures USB, so reinit it to have debug */ usbdebug_init(); #endif /* For reference print the System Agent version * after executing the UEFI PEI stage. */ u32 version = MCHBAR32(0x5034); printk(BIOS_DEBUG, "System Agent Version %d.%d.%d Build %d\n", version >> 24 , (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); /* Send ME init done for SandyBridge here. This is done * inside the SystemAgent binary on IvyBridge. */ if (BASE_REV_SNB == (pci_read_config16(PCI_CPU_DEVICE, PCI_DEVICE_ID) & BASE_REV_MASK)) intel_early_me_init_done(ME_INIT_STATUS_SUCCESS); else intel_early_me_status(); report_memory_config(); }
int intel_early_me_init_done(u8 status) { u8 reset; int count; u32 mebase_l, mebase_h; struct me_hfs hfs; struct me_did did = { .init_done = ME_INIT_DONE, .status = status }; /* MEBASE from MESEG_BASE[35:20] */ mebase_l = pci_read_config32(PCI_CPU_DEVICE, PCI_CPU_MEBASE_L); mebase_h = pci_read_config32(PCI_CPU_DEVICE, PCI_CPU_MEBASE_H) & 0xf; did.uma_base = (mebase_l >> 20) | (mebase_h << 12); /* Send message to ME */ printk(BIOS_DEBUG, "ME: Sending Init Done with status: %d, " "UMA base: 0x%04x\n", status, did.uma_base); pci_write_dword_ptr(&did, PCI_ME_H_GS); /* * The ME firmware does not respond with an ACK when NOMEM or ERROR * are sent. */ if (status == ME_INIT_STATUS_NOMEM || status == ME_INIT_STATUS_ERROR) return 0; /* Must wait for ME acknowledgement */ for (count = ME_RETRY; count > 0; --count) { pci_read_dword_ptr(&hfs, PCI_ME_HFS); if (hfs.bios_msg_ack) break; udelay(ME_DELAY); } if (!count) { printk(BIOS_ERR, "ERROR: ME failed to respond\n"); return -1; } /* Return the requested BIOS action */ printk(BIOS_NOTICE, "ME: Requested BIOS Action: %s\n", me_ack_values[hfs.ack_data]); /* Check status after acknowledgement */ intel_early_me_status(); reset = 0; switch (hfs.ack_data) { case ME_HFS_ACK_CONTINUE: /* Continue to boot */ return 0; case ME_HFS_ACK_RESET: /* Non-power cycle reset */ set_global_reset(0); reset = 0x06; break; case ME_HFS_ACK_PWR_CYCLE: /* Power cycle reset */ set_global_reset(0); reset = 0x0e; break; case ME_HFS_ACK_GBL_RESET: /* Global reset */ set_global_reset(1); reset = 0x0e; break; case ME_HFS_ACK_S3: case ME_HFS_ACK_S4: case ME_HFS_ACK_S5: break; } /* Perform the requested reset */ if (reset) { outb(reset, 0xcf9); while (1) { hlt(); } } return -1; }
void romstage_common(const struct romstage_params *params) { int boot_mode; int wake_from_s3; timestamp_init(get_initial_timestamp()); timestamp_add_now(TS_START_ROMSTAGE); if (params->bist == 0) enable_lapic(); wake_from_s3 = early_pch_init(params->gpio_map, params->rcba_config); #if CONFIG_EC_GOOGLE_CHROMEEC /* Ensure the EC is in the right mode for recovery */ google_chromeec_early_init(); #endif /* Halt if there was a built in self test failure */ report_bist_failure(params->bist); /* Perform some early chipset initialization required * before RAM initialization can work */ haswell_early_initialization(HASWELL_MOBILE); printk(BIOS_DEBUG, "Back from haswell_early_initialization()\n"); if (wake_from_s3) { #if CONFIG_HAVE_ACPI_RESUME printk(BIOS_DEBUG, "Resume from S3 detected.\n"); #else printk(BIOS_DEBUG, "Resume from S3 detected, but disabled.\n"); wake_from_s3 = 0; #endif } /* There are hard coded assumptions of 2 meaning s3 wake. Normalize * the users of the 2 literal here based off wake_from_s3. */ boot_mode = wake_from_s3 ? 2 : 0; /* Prepare USB controller early in S3 resume */ if (wake_from_s3) enable_usb_bar(); post_code(0x3a); params->pei_data->boot_mode = boot_mode; timestamp_add_now(TS_BEFORE_INITRAM); report_platform_info(); if (params->copy_spd != NULL) params->copy_spd(params->pei_data); sdram_initialize(params->pei_data); timestamp_add_now(TS_AFTER_INITRAM); post_code(0x3b); intel_early_me_status(); quick_ram_check(); post_code(0x3e); if (!wake_from_s3) { cbmem_initialize_empty(); /* Save data returned from MRC on non-S3 resumes. */ save_mrc_data(params->pei_data); } else if (cbmem_initialize()) { #if CONFIG_HAVE_ACPI_RESUME /* Failed S3 resume, reset to come up cleanly */ reset_system(); #endif } romstage_handoff_init(wake_from_s3); post_code(0x3f); if (IS_ENABLED(CONFIG_LPC_TPM)) init_tpm(wake_from_s3); }
void romstage_common(const struct romstage_params *params) { int boot_mode; int wake_from_s3; struct romstage_handoff *handoff; #if CONFIG_COLLECT_TIMESTAMPS uint64_t start_romstage_time; uint64_t before_dram_time; uint64_t after_dram_time; uint64_t base_time = (uint64_t)pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0) << 32 || pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc); #endif #if CONFIG_COLLECT_TIMESTAMPS start_romstage_time = timestamp_get(); #endif if (params->bist == 0) enable_lapic(); wake_from_s3 = early_pch_init(params->gpio_map, params->rcba_config); #if CONFIG_EC_GOOGLE_CHROMEEC /* Ensure the EC is in the right mode for recovery */ google_chromeec_early_init(); #endif /* Halt if there was a built in self test failure */ report_bist_failure(params->bist); /* Perform some early chipset initialization required * before RAM initialization can work */ haswell_early_initialization(HASWELL_MOBILE); printk(BIOS_DEBUG, "Back from haswell_early_initialization()\n"); if (wake_from_s3) { #if CONFIG_HAVE_ACPI_RESUME printk(BIOS_DEBUG, "Resume from S3 detected.\n"); #else printk(BIOS_DEBUG, "Resume from S3 detected, but disabled.\n"); wake_from_s3 = 0; #endif } /* There are hard coded assumptions of 2 meaning s3 wake. Normalize * the users of the 2 literal here based off wake_from_s3. */ boot_mode = wake_from_s3 ? 2 : 0; /* Prepare USB controller early in S3 resume */ if (wake_from_s3) enable_usb_bar(); post_code(0x3a); params->pei_data->boot_mode = boot_mode; #if CONFIG_COLLECT_TIMESTAMPS before_dram_time = timestamp_get(); #endif report_platform_info(); if (params->copy_spd != NULL) params->copy_spd(params->pei_data); sdram_initialize(params->pei_data); #if CONFIG_COLLECT_TIMESTAMPS after_dram_time = timestamp_get(); #endif post_code(0x3b); intel_early_me_status(); quick_ram_check(); post_code(0x3e); if (!wake_from_s3) { cbmem_initialize_empty(); /* Save data returned from MRC on non-S3 resumes. */ save_mrc_data(params->pei_data); } else if (cbmem_initialize()) { #if CONFIG_HAVE_ACPI_RESUME /* Failed S3 resume, reset to come up cleanly */ reset_system(); #endif } handoff = romstage_handoff_find_or_add(); if (handoff != NULL) handoff->s3_resume = wake_from_s3; else printk(BIOS_DEBUG, "Romstage handoff structure not added!\n"); post_code(0x3f); #if CONFIG_CHROMEOS init_chromeos(boot_mode); #endif #if CONFIG_COLLECT_TIMESTAMPS timestamp_init(base_time); timestamp_add(TS_START_ROMSTAGE, start_romstage_time ); timestamp_add(TS_BEFORE_INITRAM, before_dram_time ); timestamp_add(TS_AFTER_INITRAM, after_dram_time ); timestamp_add_now(TS_END_ROMSTAGE); #endif }
/** * Find the PEI executable in the ROM and execute it. * * @param pei_data: configuration data for UEFI PEI reference code */ int sdram_initialise(struct pei_data *pei_data) { unsigned version; const char *data; uint16_t done; int ret; report_platform_info(); /* Wait for ME to be ready */ ret = intel_early_me_init(); if (ret) return ret; ret = intel_early_me_uma_size(); if (ret < 0) return ret; debug("Starting UEFI PEI System Agent\n"); /* * Do not pass MRC data in for recovery mode boot, * Always pass it in for S3 resume. */ if (!recovery_mode_enabled() || pei_data->boot_mode == PEI_BOOT_RESUME) { ret = prepare_mrc_cache(pei_data); if (ret) debug("prepare_mrc_cache failed: %d\n", ret); } /* If MRC data is not found we cannot continue S3 resume. */ if (pei_data->boot_mode == PEI_BOOT_RESUME && !pei_data->mrc_input) { debug("Giving up in sdram_initialize: No MRC data\n"); reset_cpu(0); } /* Pass console handler in pei_data */ pei_data->tx_byte = console_tx_byte; debug("PEI data at %p, size %x:\n", pei_data, sizeof(*pei_data)); data = (char *)CONFIG_X86_MRC_ADDR; if (data) { int rv; int (*func)(struct pei_data *); debug("Calling MRC at %p\n", data); post_code(POST_PRE_MRC); func = (int (*)(struct pei_data *))data; rv = func(pei_data); post_code(POST_MRC); if (rv) { switch (rv) { case -1: printf("PEI version mismatch.\n"); break; case -2: printf("Invalid memory frequency.\n"); break; default: printf("MRC returned %x.\n", rv); } printf("Nonzero MRC return value.\n"); return -EFAULT; } } else { printf("UEFI PEI System Agent not found.\n"); return -ENOSYS; } #if CONFIG_USBDEBUG /* mrc.bin reconfigures USB, so reinit it to have debug */ early_usbdebug_init(); #endif version = readl(MCHBAR_REG(0x5034)); debug("System Agent Version %d.%d.%d Build %d\n", version >> 24 , (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); debug("MCR output data length %#x at %p\n", pei_data->mrc_output_len, pei_data->mrc_output); /* * Send ME init done for SandyBridge here. This is done inside the * SystemAgent binary on IvyBridge */ done = x86_pci_read_config32(PCH_DEV, PCI_DEVICE_ID); done &= BASE_REV_MASK; if (BASE_REV_SNB == done) intel_early_me_init_done(ME_INIT_STATUS_SUCCESS); else intel_early_me_status(); post_system_agent_init(pei_data); report_memory_config(); /* S3 resume: don't save scrambler seed or MRC data */ if (pei_data->boot_mode != PEI_BOOT_RESUME) { /* * This will be copied to SDRAM in reserve_arch(), then written * to SPI flash in sdram_save_mrc_data() */ gd->arch.mrc_output = (char *)pei_data->mrc_output; gd->arch.mrc_output_len = pei_data->mrc_output_len; ret = write_seeds_to_cmos(pei_data); if (ret) debug("Failed to write seeds to CMOS: %d\n", ret); } return 0; }