Andrey Petrov | 5672dcd | 2016-02-12 15:12:43 -0800 | [diff] [blame] | 1 | /* |
| 2 | * This file is part of the coreboot project. |
| 3 | * |
| 4 | * Copyright (C) 2015 Intel Corp. |
| 5 | * (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.) |
| 6 | * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.) |
| 7 | * |
| 8 | * This program is free software; you can redistribute it and/or modify |
| 9 | * it under the terms of the GNU General Public License as published by |
| 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | * (at your option) any later version. |
Martin Roth | ebabfad | 2016-04-10 11:09:16 -0600 | [diff] [blame] | 12 | * |
| 13 | * This program is distributed in the hope that it will be useful, |
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | * GNU General Public License for more details. |
Andrey Petrov | 5672dcd | 2016-02-12 15:12:43 -0800 | [diff] [blame] | 17 | */ |
| 18 | |
Furquan Shaikh | 0be3da5 | 2016-06-19 23:20:43 -0700 | [diff] [blame] | 19 | #include <arch/early_variables.h> |
Andrey Petrov | 5672dcd | 2016-02-12 15:12:43 -0800 | [diff] [blame] | 20 | #include <boot_device.h> |
| 21 | #include <cbfs.h> |
| 22 | #include <commonlib/region.h> |
| 23 | #include <console/console.h> |
| 24 | #include <fmap.h> |
Furquan Shaikh | d6c5559 | 2016-11-21 12:41:20 -0800 | [diff] [blame] | 25 | #include <soc/flash_ctrlr.h> |
Furquan Shaikh | 8065bd4 | 2016-06-21 12:50:13 -0700 | [diff] [blame] | 26 | #include <soc/mmap_boot.h> |
Andrey Petrov | 5672dcd | 2016-02-12 15:12:43 -0800 | [diff] [blame] | 27 | |
| 28 | /* |
Furquan Shaikh | 0be3da5 | 2016-06-19 23:20:43 -0700 | [diff] [blame] | 29 | * BIOS region on the flash is mapped right below 4GiB in the address |
| 30 | * space. However, 256KiB right below 4GiB is decoded by read-only SRAM and not |
| 31 | * boot media. |
| 32 | * |
Lee Leahy | 07441b5 | 2017-03-09 10:59:25 -0800 | [diff] [blame] | 33 | * +-----------+ 0 |
| 34 | * | | |
| 35 | * | | |
| 36 | * | | |
| 37 | * | | |
| 38 | * | | |
| 39 | * | | |
| 40 | * | | |
| 41 | * | | |
| 42 | * +--------+ | | |
| 43 | * | IFD | | | |
| 44 | * bios_start +---> +--------+------------------> +-----------+ 4GiB - bios_size |
| 45 | * ^ | | ^ | | |
| 46 | * | | | | | | |
| 47 | * | | | bios_mapped_size | BIOS | |
| 48 | * | | BIOS | | | | |
| 49 | * bios_size | | | | | |
| 50 | * | | | v | | |
| 51 | * | | +------------------> +-----------+ 4GiB - 256KiB |
| 52 | * | | | | Read only | |
| 53 | * v | | | SRAM | |
| 54 | * bios_end +---> +--------+ +-----------+ 4GiB |
| 55 | * | Device | |
| 56 | * | ext | |
| 57 | * +--------+ |
Furquan Shaikh | 0be3da5 | 2016-06-19 23:20:43 -0700 | [diff] [blame] | 58 | * |
Andrey Petrov | 5672dcd | 2016-02-12 15:12:43 -0800 | [diff] [blame] | 59 | */ |
Andrey Petrov | 5672dcd | 2016-02-12 15:12:43 -0800 | [diff] [blame] | 60 | |
Furquan Shaikh | 0be3da5 | 2016-06-19 23:20:43 -0700 | [diff] [blame] | 61 | static size_t bios_start CAR_GLOBAL; |
| 62 | static size_t bios_size CAR_GLOBAL; |
Andrey Petrov | 5672dcd | 2016-02-12 15:12:43 -0800 | [diff] [blame] | 63 | |
Furquan Shaikh | 0be3da5 | 2016-06-19 23:20:43 -0700 | [diff] [blame] | 64 | static struct mem_region_device shadow_dev CAR_GLOBAL; |
| 65 | static struct xlate_region_device real_dev CAR_GLOBAL; |
| 66 | |
| 67 | static void bios_mmap_init(void) |
| 68 | { |
| 69 | size_t size; |
| 70 | |
| 71 | size = car_get_var(bios_size); |
| 72 | |
| 73 | /* If bios_size is initialized, then bail out. */ |
| 74 | if (size != 0) |
| 75 | return; |
| 76 | |
| 77 | size_t start, bios_end, bios_mapped_size; |
| 78 | uintptr_t base; |
| 79 | |
| 80 | /* |
| 81 | * BIOS_BFPREG provides info about BIOS Flash Primary Region |
| 82 | * Base and Limit. |
| 83 | * Base and Limit fields are in units of 4KiB. |
| 84 | */ |
Furquan Shaikh | d6c5559 | 2016-11-21 12:41:20 -0800 | [diff] [blame] | 85 | uint32_t val = spi_flash_ctrlr_reg_read(SPIBAR_BIOS_BFPREG); |
Furquan Shaikh | 0be3da5 | 2016-06-19 23:20:43 -0700 | [diff] [blame] | 86 | |
| 87 | start = (val & SPIBAR_BFPREG_PRB_MASK) * 4 * KiB; |
| 88 | bios_end = (((val & SPIBAR_BFPREG_PRL_MASK) >> |
| 89 | SPIBAR_BFPREG_PRL_SHIFT) + 1) * 4 * KiB; |
| 90 | size = bios_end - start; |
| 91 | |
Furquan Shaikh | 0be3da5 | 2016-06-19 23:20:43 -0700 | [diff] [blame] | 92 | /* BIOS region is mapped right below 4G. */ |
| 93 | base = 4ULL * GiB - size; |
| 94 | |
| 95 | /* |
| 96 | * The 256 KiB right below 4G are decoded by readonly SRAM, |
| 97 | * not boot media. |
| 98 | */ |
| 99 | bios_mapped_size = size - 256 * KiB; |
| 100 | |
| 101 | struct mem_region_device *shadow_dev_ptr; |
| 102 | struct xlate_region_device *real_dev_ptr; |
| 103 | shadow_dev_ptr = car_get_var_ptr(&shadow_dev); |
| 104 | real_dev_ptr = car_get_var_ptr(&real_dev); |
| 105 | |
Antonello Dettori | e5f48d2 | 2016-06-22 21:09:08 +0200 | [diff] [blame] | 106 | mem_region_device_ro_init(shadow_dev_ptr, (void *)base, |
Furquan Shaikh | 0be3da5 | 2016-06-19 23:20:43 -0700 | [diff] [blame] | 107 | bios_mapped_size); |
| 108 | |
Antonello Dettori | e5f48d2 | 2016-06-22 21:09:08 +0200 | [diff] [blame] | 109 | xlate_region_device_ro_init(real_dev_ptr, &shadow_dev_ptr->rdev, |
Furquan Shaikh | 0be3da5 | 2016-06-19 23:20:43 -0700 | [diff] [blame] | 110 | start, bios_mapped_size, |
| 111 | CONFIG_ROM_SIZE); |
| 112 | |
| 113 | car_set_var(bios_start, start); |
| 114 | car_set_var(bios_size, size); |
| 115 | } |
Andrey Petrov | 5672dcd | 2016-02-12 15:12:43 -0800 | [diff] [blame] | 116 | |
| 117 | const struct region_device *boot_device_ro(void) |
| 118 | { |
Furquan Shaikh | 0be3da5 | 2016-06-19 23:20:43 -0700 | [diff] [blame] | 119 | bios_mmap_init(); |
| 120 | |
| 121 | struct xlate_region_device *real_dev_ptr; |
| 122 | real_dev_ptr = car_get_var_ptr(&real_dev); |
| 123 | |
| 124 | return &real_dev_ptr->rdev; |
Andrey Petrov | 5672dcd | 2016-02-12 15:12:43 -0800 | [diff] [blame] | 125 | } |
| 126 | |
| 127 | static int iafw_boot_region_properties(struct cbfs_props *props) |
| 128 | { |
| 129 | struct region regn; |
| 130 | |
| 131 | /* use fmap to locate CBFS area */ |
| 132 | if (fmap_locate_area("COREBOOT", ®n)) |
| 133 | return -1; |
| 134 | |
| 135 | props->offset = region_offset(®n); |
| 136 | props->size = region_sz(®n); |
| 137 | |
| 138 | printk(BIOS_DEBUG, "CBFS @ %zx size %zx\n", props->offset, props->size); |
| 139 | |
| 140 | return 0; |
| 141 | } |
| 142 | |
| 143 | /* |
| 144 | * Named cbfs_master_header_locator so that it overrides the default, but |
| 145 | * incompatible locator in cbfs.c |
| 146 | */ |
| 147 | const struct cbfs_locator cbfs_master_header_locator = { |
| 148 | .name = "IAFW Locator", |
| 149 | .locate = iafw_boot_region_properties, |
| 150 | }; |
Alexandru Gagniuc | 0a4b47e | 2016-03-03 13:16:36 -0800 | [diff] [blame] | 151 | |
Furquan Shaikh | 8065bd4 | 2016-06-21 12:50:13 -0700 | [diff] [blame] | 152 | size_t get_bios_size(void) |
| 153 | { |
| 154 | bios_mmap_init(); |
| 155 | return car_get_var(bios_size); |
| 156 | } |