1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3 * UPL handoff generation
4 *
5 * Copyright 2024 Google LLC
6 * Written by Simon Glass <sjg@chromium.org>
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);
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);
321 #endif /* USE_HOSTCC */
322
323 #if CONFIG_IS_ENABLED(UPL) && defined(CONFIG_XPL_BUILD)
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
upl_set_fit_addr(ulong fit)342 static inline void upl_set_fit_addr(ulong fit) {}
upl_set_fit_info(ulong fit,int conf_offset,ulong entry_addr)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 */
upl_add_image(const void * fit,int node,ulong load_addr,ulong size)367 static inline int upl_add_image(const void *fit, int node, ulong load_addr,
368 ulong size)
369 {
370 if (CONFIG_IS_ENABLED(UPL) && IS_ENABLED(CONFIG_XPL_BUILD)) {
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 */
383