]>
Commit | Line | Data |
---|---|---|
90469da3 SG |
1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
2 | /* | |
3 | * UPL handoff generation | |
4 | * | |
5 | * Copyright 2024 Google LLC | |
6 | * Written by Simon Glass <[email protected]> | |
7 | */ | |
8 | ||
9 | #ifndef __UPL_WRITE_H | |
10 | #define __UPL_WRITE_H | |
11 | ||
12 | #ifndef USE_HOSTCC | |
13 | ||
14 | #include <alist.h> | |
15 | #include <image.h> | |
16 | #include <dm/ofnode_decl.h> | |
17 | ||
18 | struct unit_test_state; | |
19 | ||
20 | #define UPLP_ADDRESS_CELLS "#address-cells" | |
21 | #define UPLP_SIZE_CELLS "#size-cells" | |
22 | ||
23 | #define UPLN_OPTIONS "options" | |
24 | #define UPLN_UPL_PARAMS "upl-params" | |
25 | #define UPLP_SMBIOS "smbios" | |
26 | #define UPLP_ACPI "acpi" | |
27 | #define UPLP_BOOTMODE "bootmode" | |
28 | #define UPLP_ADDR_WIDTH "addr-width" | |
29 | #define UPLP_ACPI_NVS_SIZE "acpi-nvs-size" | |
30 | ||
31 | #define UPLPATH_UPL_IMAGE "/options/upl-image" | |
32 | #define UPLN_UPL_IMAGE "upl-image" | |
33 | #define UPLN_IMAGE "image" | |
34 | #define UPLP_FIT "fit" | |
35 | #define UPLP_CONF_OFFSET "conf-offset" | |
36 | #define UPLP_LOAD "load" | |
37 | #define UPLP_SIZE "size" | |
38 | #define UPLP_OFFSET "offset" | |
39 | #define UPLP_DESCRIPTION "description" | |
40 | ||
41 | #define UPLN_MEMORY "memory" | |
42 | #define UPLP_HOTPLUGGABLE "hotpluggable" | |
43 | ||
44 | #define UPLPATH_MEMORY_MAP "/memory-map" | |
45 | #define UPLN_MEMORY_MAP "memory-map" | |
46 | #define UPLP_USAGE "usage" | |
47 | ||
48 | #define UPLN_MEMORY_RESERVED "reserved-memory" | |
49 | #define UPLPATH_MEMORY_RESERVED "/reserved-memory" | |
50 | #define UPLP_NO_MAP "no-map" | |
51 | ||
52 | #define UPLN_SERIAL "serial" | |
53 | #define UPLP_REG "reg" | |
54 | #define UPLP_COMPATIBLE "compatible" | |
55 | #define UPLP_CLOCK_FREQUENCY "clock-frequency" | |
56 | #define UPLP_CURRENT_SPEED "current-speed" | |
57 | #define UPLP_REG_IO_SHIFT "reg-io-shift" | |
58 | #define UPLP_REG_OFFSET "reg-offset" | |
59 | #define UPLP_REG_IO_WIDTH "reg-io-width" | |
60 | #define UPLP_VIRTUAL_REG "virtual-reg" | |
61 | #define UPLP_ACCESS_TYPE "access-type" | |
62 | ||
63 | #define UPLN_GRAPHICS "framebuffer" | |
64 | #define UPLC_GRAPHICS "simple-framebuffer" | |
65 | #define UPLP_WIDTH "width" | |
66 | #define UPLP_HEIGHT "height" | |
67 | #define UPLP_STRIDE "stride" | |
68 | #define UPLP_GRAPHICS_FORMAT "format" | |
69 | ||
70 | /** | |
71 | * enum upl_boot_mode - Encodes the boot mode | |
72 | * | |
73 | * Each is a bit number from the boot_mode mask | |
74 | */ | |
75 | enum upl_boot_mode { | |
76 | UPLBM_FULL, | |
77 | UPLBM_MINIMAL, | |
78 | UPLBM_FAST, | |
79 | UPLBM_DIAG, | |
80 | UPLBM_DEFAULT, | |
81 | UPLBM_S2, | |
82 | UPLBM_S3, | |
83 | UPLBM_S4, | |
84 | UPLBM_S5, | |
85 | UPLBM_FACTORY, | |
86 | UPLBM_FLASH, | |
87 | UPLBM_RECOVERY, | |
88 | ||
89 | UPLBM_COUNT, | |
90 | }; | |
91 | ||
92 | /** | |
93 | * struct upl_image - UPL image informaiton | |
94 | * | |
95 | * @load: Address image was loaded to | |
96 | * @size: Size of image in bytes | |
97 | * @offset: Offset of the image in the FIT (0=none) | |
98 | * @desc: Description of the iamge (taken from the FIT) | |
99 | */ | |
100 | struct upl_image { | |
101 | ulong load; | |
102 | ulong size; | |
103 | uint offset; | |
104 | const char *description; | |
105 | }; | |
106 | ||
107 | /** | |
108 | * struct memregion - Information about a region of memory | |
109 | * | |
110 | * @base: Base address | |
111 | * @size: Size in bytes | |
112 | */ | |
113 | struct memregion { | |
114 | ulong base; | |
115 | ulong size; | |
116 | }; | |
117 | ||
118 | /** | |
119 | * struct upl_mem - Information about physical-memory layout | |
120 | * | |
121 | * TODO: Figure out initial-mapped-area | |
122 | * | |
123 | * @region: Memory region list (struct memregion) | |
124 | * @hotpluggable: true if hotpluggable | |
125 | */ | |
126 | struct upl_mem { | |
127 | struct alist region; | |
128 | bool hotpluggable; | |
129 | }; | |
130 | ||
131 | /** | |
132 | * enum upl_usage - Encodes the usage | |
133 | * | |
134 | * Each is a bit number from the usage mask | |
135 | */ | |
136 | enum upl_usage { | |
137 | UPLUS_ACPI_RECLAIM, | |
138 | UPLUS_ACPI_NVS, | |
139 | UPLUS_BOOT_CODE, | |
140 | UPLUS_BOOT_DATA, | |
141 | UPLUS_RUNTIME_CODE, | |
142 | UPLUS_RUNTIME_DATA, | |
143 | UPLUS_COUNT | |
144 | }; | |
145 | ||
146 | /** | |
147 | * struct upl_memmap - Information about logical-memory layout | |
148 | * | |
149 | * @name: Node name to use | |
150 | * @region: Memory region list (struct memregion) | |
151 | * @usage: Memory-usage mask (enum upl_usage) | |
152 | */ | |
153 | struct upl_memmap { | |
154 | const char *name; | |
155 | struct alist region; | |
156 | uint usage; | |
157 | }; | |
158 | ||
159 | /** | |
160 | * struct upl_memres - Reserved memory | |
161 | * | |
162 | * @name: Node name to use | |
163 | * @region: Reserved memory region list (struct memregion) | |
164 | * @no_map: true to indicate that a virtual mapping must not be created | |
165 | */ | |
166 | struct upl_memres { | |
167 | const char *name; | |
168 | struct alist region; | |
169 | bool no_map; | |
170 | }; | |
171 | ||
172 | enum upl_serial_access_type { | |
173 | UPLSAT_MMIO, | |
174 | UPLSAT_IO, | |
175 | }; | |
176 | ||
177 | /* serial defaults */ | |
178 | enum { | |
179 | UPLD_REG_IO_SHIFT = 0, | |
180 | UPLD_REG_OFFSET = 0, | |
181 | UPLD_REG_IO_WIDTH = 1, | |
182 | }; | |
183 | ||
184 | /** | |
185 | * enum upl_access_type - Access types | |
186 | * | |
187 | * @UPLAT_MMIO: Memory-mapped I/O | |
188 | * @UPLAT_IO: Separate I/O | |
189 | */ | |
190 | enum upl_access_type { | |
191 | UPLAT_MMIO, | |
192 | UPLAT_IO, | |
193 | }; | |
194 | ||
195 | /** | |
196 | * struct upl_serial - Serial console | |
197 | * | |
198 | * @compatible: Compatible string (NULL if there is no serial console) | |
199 | * @clock_frequency: Input clock frequency of UART | |
200 | * @current_speed: Current baud rate of UART | |
201 | * @reg: List of base address and size of registers (struct memregion) | |
202 | * @reg_shift_log2: log2 of distance between each register | |
203 | * @reg_offset: Offset of registers from the base address | |
204 | * @reg_width: Register width in bytes | |
205 | * @virtual_reg: Virtual register access (0 for none) | |
206 | * @access_type: Register access type to use | |
207 | */ | |
208 | struct upl_serial { | |
209 | const char *compatible; | |
210 | uint clock_frequency; | |
211 | uint current_speed; | |
212 | struct alist reg; | |
213 | uint reg_io_shift; | |
214 | uint reg_offset; | |
215 | uint reg_io_width; | |
216 | ulong virtual_reg; | |
217 | enum upl_serial_access_type access_type; | |
218 | }; | |
219 | ||
220 | /** | |
221 | * enum upl_graphics_format - Graphics formats | |
222 | * | |
223 | * @UPLGF_ARGB32: 32bpp format using 0xaarrggbb | |
224 | * @UPLGF_ABGR32: 32bpp format using 0xaabbggrr | |
225 | * @UPLGF_ARGB64: 64bpp format using 0xaaaabbbbggggrrrr | |
226 | */ | |
227 | enum upl_graphics_format { | |
228 | UPLGF_ARGB32, | |
229 | UPLGF_ABGR32, | |
230 | UPLGF_ABGR64, | |
231 | }; | |
232 | ||
233 | /** | |
234 | * @reg: List of base address and size of registers (struct memregion) | |
235 | * @width: Width of display in pixels | |
236 | * @height: Height of display in pixels | |
237 | * @stride: Number of bytes from one line to the next | |
238 | * @format: Pixel format | |
239 | */ | |
240 | struct upl_graphics { | |
241 | struct alist reg; | |
242 | uint width; | |
243 | uint height; | |
244 | uint stride; | |
245 | enum upl_graphics_format format; | |
246 | }; | |
247 | ||
248 | /* | |
249 | * Information about the UPL state | |
250 | * | |
251 | * @addr_cells: Number of address cells used in the handoff | |
252 | * @size_cells: Number of size cells used in the handoff | |
253 | * @bootmode: Boot-mode mask (enum upl_boot_mode) | |
254 | * @fit: Address of FIT image that was loaded | |
255 | * @conf_offset: Offset in FIT of the configuration that was selected | |
256 | * @addr_width: Adress-bus width of machine, e.g. 46 for 46 bits | |
257 | * @acpi_nvs_size: Size of the ACPI non-volatile-storage area in bytes | |
258 | * @image: Information about each image (struct upl_image) | |
259 | * @mem: Information about physical-memory regions (struct upl_mem) | |
260 | * @nennap: Information about logical-memory regions (struct upl_memmap) | |
261 | * @nennap: Information about reserved-memory regions (struct upl_memres) | |
262 | */ | |
263 | struct upl { | |
264 | int addr_cells; | |
265 | int size_cells; | |
266 | ||
267 | ulong smbios; | |
268 | ulong acpi; | |
269 | uint bootmode; | |
270 | ulong fit; | |
271 | uint conf_offset; | |
272 | uint addr_width; | |
273 | uint acpi_nvs_size; | |
274 | ||
275 | struct alist image; | |
276 | struct alist mem; | |
277 | struct alist memmap; | |
278 | struct alist memres; | |
279 | struct upl_serial serial; | |
280 | struct upl_graphics graphics; | |
281 | }; | |
282 | ||
283 | /** | |
284 | * upl_write_handoff() - Write a Unversal Payload handoff structure | |
285 | * | |
286 | * upl: UPL state to write | |
287 | * @root: root node to write it to | |
288 | * @skip_existing: Avoid recreating any nodes which already exist in the | |
289 | * devicetree. For example, if there is a serial node, just leave it alone, | |
290 | * since don't need to create a new one | |
291 | * Return: 0 on success, -ve on error | |
292 | */ | |
293 | int upl_write_handoff(const struct upl *upl, ofnode root, bool skip_existing); | |
294 | ||
295 | /** | |
296 | * upl_create_handoff_tree() - Write a Unversal Payload handoff structure | |
297 | * | |
298 | * upl: UPL state to write | |
299 | * @treep: Returns a new tree containing the handoff | |
300 | * Return: 0 on success, -ve on error | |
301 | */ | |
302 | int upl_create_handoff_tree(const struct upl *upl, oftree *treep); | |
303 | ||
304 | /** | |
305 | * upl_read_handoff() - Read a Unversal Payload handoff structure | |
306 | * | |
307 | * upl: UPL state to read into | |
308 | * @tree: Devicetree containing the data to read | |
309 | * Return: 0 on success, -ve on error | |
310 | */ | |
311 | int upl_read_handoff(struct upl *upl, oftree tree); | |
637be2e5 SG |
312 | |
313 | /** | |
314 | * upl_get_test_data() - Fill a UPL with some test data | |
315 | * | |
316 | * @uts: Test state (can be uninited) | |
317 | * @upl: Returns test data | |
318 | * Return: 0 on success, 1 on error | |
319 | */ | |
320 | int upl_get_test_data(struct unit_test_state *uts, struct upl *upl); | |
90469da3 SG |
321 | #endif /* USE_HOSTCC */ |
322 | ||
f38956a6 | 323 | #if CONFIG_IS_ENABLED(UPL) && defined(CONFIG_XPL_BUILD) |
90469da3 SG |
324 | |
325 | /** | |
326 | * upl_set_fit_info() - Set up basic info about the FIT | |
327 | * | |
328 | * @fit: Address of FIT | |
329 | * @conf_offset: Configuration node being used | |
330 | * @entry_addr: Entry address for next phase | |
331 | */ | |
332 | void upl_set_fit_info(ulong fit, int conf_offset, ulong entry_addr); | |
333 | ||
334 | /** | |
335 | * upl_set_fit_addr() - Set up the address of the FIT | |
336 | * | |
337 | * @fit: Address of FIT | |
338 | */ | |
339 | void upl_set_fit_addr(ulong fit); | |
340 | ||
341 | #else | |
342 | static inline void upl_set_fit_addr(ulong fit) {} | |
343 | static inline void upl_set_fit_info(ulong fit, int conf_offset, | |
344 | ulong entry_addr) {} | |
345 | #endif /* UPL && SPL */ | |
346 | ||
347 | /** | |
348 | * _upl_add_image() - Internal function to add a new image to the UPL | |
349 | * | |
350 | * @node: Image node offset in FIT | |
351 | * @load_addr: Address to which images was loaded | |
352 | * @size: Image size in bytes | |
353 | * @desc: Description of image | |
354 | * Return: 0 if OK, -ENOMEM if out of memory | |
355 | */ | |
356 | int _upl_add_image(int node, ulong load_addr, ulong size, const char *desc); | |
357 | ||
358 | /** | |
359 | * upl_add_image() - Add a new image to the UPL | |
360 | * | |
361 | * @fit: Pointer to FIT | |
362 | * @node: Image node offset in FIT | |
363 | * @load_addr: Address to which images was loaded | |
364 | * @size: Image size in bytes | |
365 | * Return: 0 if OK, -ENOMEM if out of memory | |
366 | */ | |
367 | static inline int upl_add_image(const void *fit, int node, ulong load_addr, | |
368 | ulong size) | |
369 | { | |
f38956a6 | 370 | if (CONFIG_IS_ENABLED(UPL) && IS_ENABLED(CONFIG_XPL_BUILD)) { |
90469da3 SG |
371 | const char *desc = fdt_getprop(fit, node, FIT_DESC_PROP, NULL); |
372 | ||
373 | return _upl_add_image(node, load_addr, size, desc); | |
374 | } | |
375 | ||
376 | return 0; | |
377 | } | |
378 | ||
379 | /** upl_init() - Set up a UPL struct */ | |
380 | void upl_init(struct upl *upl); | |
381 | ||
382 | #endif /* __UPL_WRITE_H */ |