/** * 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) { unsigned long entry; printk(BIOS_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 == 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) { post_code(POST_RESUME_FAILURE); 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 = (unsigned long)cbfs_get_file_content( CBFS_DEFAULT_MEDIA, "mrc.bin", CBFS_TYPE_MRC, NULL); if (entry) { int rv; asm volatile ( "call *%%ecx\n\t" :"=a" (rv) : "c" (entry), "a" (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 {
int dram_init(void) { struct pei_data _pei_data __aligned(8); struct pei_data *pei_data = &_pei_data; struct udevice *dev, *me_dev, *pch_dev; struct chipset_power_state ps; const void *spd_data; int ret, size; memset(pei_data, '\0', sizeof(struct pei_data)); /* Print ME state before MRC */ ret = syscon_get_by_driver_data(X86_SYSCON_ME, &me_dev); if (ret) return ret; intel_me_status(me_dev); /* Save ME HSIO version */ ret = uclass_first_device(UCLASS_PCH, &pch_dev); if (ret) return ret; if (!pch_dev) return -ENODEV; power_state_get(pch_dev, &ps); intel_me_hsio_version(me_dev, &ps.hsio_version, &ps.hsio_checksum); broadwell_fill_pei_data(pei_data); mainboard_fill_pei_data(pei_data); ret = uclass_first_device(UCLASS_NORTHBRIDGE, &dev); if (ret) return ret; if (!dev) return -ENODEV; size = 256; ret = mrc_locate_spd(dev, size, &spd_data); if (ret) return ret; memcpy(pei_data->spd_data[0][0], spd_data, size); memcpy(pei_data->spd_data[1][0], spd_data, size); ret = prepare_mrc_cache(pei_data); if (ret) debug("prepare_mrc_cache failed: %d\n", ret); debug("PEI version %#x\n", pei_data->pei_version); ret = mrc_common_init(dev, pei_data, true); if (ret) return ret; debug("Memory init done\n"); ret = sdram_find(dev); if (ret) return ret; gd->ram_size = gd->arch.meminfo.total_32bit_memory; debug("RAM size %llx\n", (unsigned long long)gd->ram_size); debug("MRC output data length %#x at %p\n", pei_data->data_to_save_size, pei_data->data_to_save); /* S3 resume: don't save scrambler seed or MRC data */ if (pei_data->boot_mode != SLEEP_STATE_S3) { /* * This will be copied to SDRAM in reserve_arch(), then written * to SPI flash in mrccache_save() */ gd->arch.mrc_output = (char *)pei_data->data_to_save; gd->arch.mrc_output_len = pei_data->data_to_save_size; } gd->arch.pei_meminfo = pei_data->meminfo; return 0; }
/** * 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(); }
/** * 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; }