xref: /aosp_15_r20/external/coreboot/src/soc/intel/common/block/fast_spi/mmap_boot.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 /*
4  * This file provides a custom boot media device for the platforms that support additional
5  * window for BIOS regions greater than 16MiB. If the mainboard uses a smaller BIOS region, then
6  * the additional window is unused.
7  */
8 
9 #include <boot_device.h>
10 #include <commonlib/region.h>
11 #include <console/console.h>
12 #include <fmap.h>
13 #include <intelblocks/fast_spi.h>
14 #include <spi_flash.h>
15 
16 enum window_type {
17 	/* Fixed decode window of max 16MiB size just below 4G boundary */
18 	FIXED_DECODE_WINDOW,
19 	/* Additional decode window for mapping BIOS region greater than 16MiB */
20 	EXT_BIOS_DECODE_WINDOW,
21 	TOTAL_DECODE_WINDOWS,
22 };
23 
24 static struct xlate_region_device real_dev;
25 static struct mem_region_device shadow_devs[TOTAL_DECODE_WINDOWS];
26 static struct xlate_window real_dev_windows[TOTAL_DECODE_WINDOWS];
27 
initialize_window(enum window_type type,uintptr_t host_base,uintptr_t flash_base,size_t size)28 static void initialize_window(enum window_type type, uintptr_t host_base,
29 			      uintptr_t flash_base, size_t size)
30 {
31 	mem_region_device_ro_init(&shadow_devs[type], (void *)host_base, size);
32 	xlate_window_init(&real_dev_windows[type], &shadow_devs[type].rdev,
33 			  flash_base, size);
34 	printk(BIOS_INFO, "MMAP window: SPI flash base=0x%lx, Host base=0x%lx, Size=0x%zx\n",
35 	       flash_base, host_base, size);
36 }
37 
38 /*
39  *
40  *                                                                      +--------------+
41  *                                                                      |              |
42  *                                                                      |              |
43  *                                                                      |              |
44  *      ^     +------------+--------------------------^--------------------------------+ 0xffffffff
45  *      |     |            |                          |                 |              |
46  *      |     |            |                          |                 |              |
47  *      |     |            |                          +                 | FIXED        |
48  *      |     |            |                     fixed_win_size         | DECODE       |
49  *      |     |  BIOS      |                          +                 | WINDOW       |
50  *      +     |  region    |                          |                 |              |
51  *  bios_size | (Region 1) |                          |                 |              |
52  *      +     |            |                          |                 |              |
53  *      |     |            |                          |                 |              |
54  *      |     |            | fixed_win_flash_base+----v--------------------------------+ fixed_win_host_base
55  *      |     |            |                     |                      |              |
56  *      |     |            |                     |                      |              |
57  *      |     |            |                     |                      | Other MMIO   |
58  *      v     |            |                     |                      |              |
59  * bios_start +------------+ ext_win_flash_base  |                      |              |
60  *            |            |            +        |                      |              |
61  *            |            |            |        |                      |              |
62  *            |            |            |        |                      |              |
63  *            |            |            |        +-----^------------------------------------------------------------^
64  *          0 +------------+            |              |                |              |                            |
65  *                                      |              +                | EXT_BIOS     |                            |
66  *            SPI flash                 |         ext_win_size          | DECODE       |                            |
67  *            address                   |              +                | WINDOW       |                            +
68  *            space                     |              |                |              |                    CONFIG_EXT_BIOS_WIN_SIZE
69  *                                      +--------------v-------------------------------+ ext_win_host_base          +
70  *                                                                      |              |                            |
71  *                                                                      | Unused       |                            |
72  *                                                                      |              |                            |
73  *                                                                      +--------------+ CONFIG_EXT_BIOS_WIN_BASE+--v
74  *                                                                      |              |
75  *                                                                      |              |
76  *                                                                      |              |
77  *                                                                      +--------------+
78  *
79  *                                                                       Host address
80  *                                                                       space
81  */
bios_mmap_init(void)82 static void bios_mmap_init(void)
83 {
84 	static bool init_done;
85 
86 	size_t bios_size, bios_start;
87 
88 	uintptr_t fixed_win_host_base, fixed_win_flash_base;
89 	uintptr_t ext_win_host_base, ext_win_flash_base;
90 	size_t fixed_win_size, ext_win_size;
91 
92 	size_t win_count = 0;
93 
94 	if (init_done)
95 		return;
96 
97 	/* Read the offset and size of BIOS region in the SPI flash address space. */
98 	bios_start = fast_spi_get_bios_region(&bios_size);
99 
100 	/*
101 	 * By default, fixed decode window (maximum size 16MiB) is mapped just below the 4G
102 	 * boundary. This window maps the top part of the BIOS region in the SPI flash address
103 	 * space to the host address space.
104 	 */
105 	fixed_win_size = MIN(16 * MiB, bios_size);
106 	fixed_win_host_base = 4ULL * GiB - fixed_win_size;
107 	fixed_win_flash_base = bios_start + bios_size - fixed_win_size;
108 
109 	initialize_window(FIXED_DECODE_WINDOW, fixed_win_host_base, fixed_win_flash_base,
110 			  fixed_win_size);
111 	win_count++;
112 
113 	_Static_assert(CONFIG_EXT_BIOS_WIN_BASE != 0, "Extended BIOS window base cannot be 0!");
114 	_Static_assert(CONFIG_EXT_BIOS_WIN_SIZE != 0, "Extended BIOS window size cannot be 0!");
115 
116 	/*
117 	 * Remaining portion of the BIOS region up to a maximum of CONFIG_EXT_BIOS_WIN_SIZE is
118 	 * mapped at the top of the extended window if the BIOS region is greater than 16MiB.
119 	 *
120 	 * If the BIOS region is not greater than 16MiB, then the extended window is not
121 	 * enabled.
122 	 */
123 	ext_win_size = MIN(CONFIG_EXT_BIOS_WIN_SIZE, bios_size - fixed_win_size);
124 
125 	if (ext_win_size) {
126 		ext_win_host_base = CONFIG_EXT_BIOS_WIN_BASE + CONFIG_EXT_BIOS_WIN_SIZE -
127 			ext_win_size;
128 		ext_win_flash_base = fixed_win_flash_base - ext_win_size;
129 		initialize_window(EXT_BIOS_DECODE_WINDOW, ext_win_host_base,
130 				  ext_win_flash_base, ext_win_size);
131 		win_count++;
132 	}
133 
134 	xlate_region_device_ro_init(&real_dev, win_count, real_dev_windows, CONFIG_ROM_SIZE);
135 
136 	init_done = true;
137 }
138 
boot_device_ro(void)139 const struct region_device *boot_device_ro(void)
140 {
141 	bios_mmap_init();
142 
143 	return &real_dev.rdev;
144 }
145 
fast_spi_get_ext_bios_window(uintptr_t * base,size_t * size)146 void fast_spi_get_ext_bios_window(uintptr_t *base, size_t *size)
147 {
148 	const struct region_device *rd = &shadow_devs[EXT_BIOS_DECODE_WINDOW].rdev;
149 
150 	bios_mmap_init();
151 
152 	*size = region_device_sz(rd);
153 
154 	if (*size == 0) {
155 		*base = 0;
156 	} else {
157 		/*
158 		 * This is a memory region device. So, mmap returns the base address of the
159 		 * device. Also, as this is a memory region device, unmap is a no-op.
160 		 */
161 		*base = (uintptr_t)rdev_mmap_full(rd);
162 	}
163 }
164 
spi_flash_get_mmap_windows(struct flash_mmap_window * table)165 uint32_t spi_flash_get_mmap_windows(struct flash_mmap_window *table)
166 {
167 	int i;
168 	uint32_t count = 0;
169 
170 	bios_mmap_init();
171 
172 	for (i = 0; i < TOTAL_DECODE_WINDOWS; i++) {
173 		if (region_sz(&real_dev_windows[i].sub_region) == 0)
174 			continue;
175 
176 		count++;
177 		table->flash_base = region_offset(&real_dev_windows[i].sub_region);
178 		table->host_base = (uintptr_t)rdev_mmap_full(&shadow_devs[i].rdev);
179 		table->size = region_sz(&real_dev_windows[i].sub_region);
180 
181 		table++;
182 	}
183 
184 	return count;
185 }
186