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