/* * This file is part of the coreboot project. * * Copyright (C) 2015 Intel Corp. * (Written by Andrey Petrov for Intel Corp.) * (Written by Alexandru Gagniuc for Intel Corp.) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include #include #include #include #include #include #include /* * BIOS region on the flash is mapped right below 4GiB in the address * space. However, 256KiB right below 4GiB is decoded by read-only SRAM and not * boot media. * * +-----------+ 0 * | | * | | * | | * | | * | | * | | * | | * | | * +--------+ | | * | IFD | | | * bios_start +---> +--------+------------------> +-----------+ 4GiB - bios_size * ^ | | ^ | | * | | | | | | * | | | bios_mapped_size | BIOS | * | | BIOS | | | | * bios_size | | | | | * | | | v | | * | | +------------------> +-----------+ 4GiB - 256KiB * | | | | Read only | * v | | | SRAM | * bios_end +---> +--------+ +-----------+ 4GiB * | Device | * | ext | * +--------+ * */ static size_t bios_size CAR_GLOBAL; static struct mem_region_device shadow_dev CAR_GLOBAL; static struct xlate_region_device real_dev CAR_GLOBAL; static void bios_mmap_init(void) { size_t size, start, bios_mapped_size; uintptr_t base; size = car_get_var(bios_size); /* If bios_size is initialized, then bail out. */ if (size != 0) return; start = fast_spi_get_bios_region(&size); /* BIOS region is mapped right below 4G. */ base = 4ULL * GiB - size; /* * The 256 KiB right below 4G are decoded by readonly SRAM, * not boot media. */ bios_mapped_size = size - 256 * KiB; struct mem_region_device *shadow_dev_ptr; struct xlate_region_device *real_dev_ptr; shadow_dev_ptr = car_get_var_ptr(&shadow_dev); real_dev_ptr = car_get_var_ptr(&real_dev); mem_region_device_ro_init(shadow_dev_ptr, (void *)base, bios_mapped_size); xlate_region_device_ro_init(real_dev_ptr, &shadow_dev_ptr->rdev, start, bios_mapped_size, CONFIG_ROM_SIZE); car_set_var(bios_size, size); } const struct region_device *boot_device_ro(void) { bios_mmap_init(); struct xlate_region_device *real_dev_ptr; real_dev_ptr = car_get_var_ptr(&real_dev); return &real_dev_ptr->rdev; } static int iafw_boot_region_properties(struct cbfs_props *props) { struct region regn; /* use fmap to locate CBFS area */ if (fmap_locate_area("COREBOOT", ®n)) return -1; props->offset = region_offset(®n); props->size = region_sz(®n); printk(BIOS_DEBUG, "CBFS @ %zx size %zx\n", props->offset, props->size); return 0; } /* * Named cbfs_master_header_locator so that it overrides the default, but * incompatible locator in cbfs.c */ const struct cbfs_locator cbfs_master_header_locator = { .name = "IAFW Locator", .locate = iafw_boot_region_properties, };