diff options
Diffstat (limited to 'include/upl.h')
-rw-r--r-- | include/upl.h | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/include/upl.h b/include/upl.h new file mode 100644 index 00000000000..4d0eca88047 --- /dev/null +++ b/include/upl.h @@ -0,0 +1,382 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * UPL handoff generation + * + * Copyright 2024 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#ifndef __UPL_WRITE_H +#define __UPL_WRITE_H + +#ifndef USE_HOSTCC + +#include <alist.h> +#include <image.h> +#include <dm/ofnode_decl.h> + +struct unit_test_state; + +#define UPLP_ADDRESS_CELLS "#address-cells" +#define UPLP_SIZE_CELLS "#size-cells" + +#define UPLN_OPTIONS "options" +#define UPLN_UPL_PARAMS "upl-params" +#define UPLP_SMBIOS "smbios" +#define UPLP_ACPI "acpi" +#define UPLP_BOOTMODE "bootmode" +#define UPLP_ADDR_WIDTH "addr-width" +#define UPLP_ACPI_NVS_SIZE "acpi-nvs-size" + +#define UPLPATH_UPL_IMAGE "/options/upl-image" +#define UPLN_UPL_IMAGE "upl-image" +#define UPLN_IMAGE "image" +#define UPLP_FIT "fit" +#define UPLP_CONF_OFFSET "conf-offset" +#define UPLP_LOAD "load" +#define UPLP_SIZE "size" +#define UPLP_OFFSET "offset" +#define UPLP_DESCRIPTION "description" + +#define UPLN_MEMORY "memory" +#define UPLP_HOTPLUGGABLE "hotpluggable" + +#define UPLPATH_MEMORY_MAP "/memory-map" +#define UPLN_MEMORY_MAP "memory-map" +#define UPLP_USAGE "usage" + +#define UPLN_MEMORY_RESERVED "reserved-memory" +#define UPLPATH_MEMORY_RESERVED "/reserved-memory" +#define UPLP_NO_MAP "no-map" + +#define UPLN_SERIAL "serial" +#define UPLP_REG "reg" +#define UPLP_COMPATIBLE "compatible" +#define UPLP_CLOCK_FREQUENCY "clock-frequency" +#define UPLP_CURRENT_SPEED "current-speed" +#define UPLP_REG_IO_SHIFT "reg-io-shift" +#define UPLP_REG_OFFSET "reg-offset" +#define UPLP_REG_IO_WIDTH "reg-io-width" +#define UPLP_VIRTUAL_REG "virtual-reg" +#define UPLP_ACCESS_TYPE "access-type" + +#define UPLN_GRAPHICS "framebuffer" +#define UPLC_GRAPHICS "simple-framebuffer" +#define UPLP_WIDTH "width" +#define UPLP_HEIGHT "height" +#define UPLP_STRIDE "stride" +#define UPLP_GRAPHICS_FORMAT "format" + +/** + * enum upl_boot_mode - Encodes the boot mode + * + * Each is a bit number from the boot_mode mask + */ +enum upl_boot_mode { + UPLBM_FULL, + UPLBM_MINIMAL, + UPLBM_FAST, + UPLBM_DIAG, + UPLBM_DEFAULT, + UPLBM_S2, + UPLBM_S3, + UPLBM_S4, + UPLBM_S5, + UPLBM_FACTORY, + UPLBM_FLASH, + UPLBM_RECOVERY, + + UPLBM_COUNT, +}; + +/** + * struct upl_image - UPL image informaiton + * + * @load: Address image was loaded to + * @size: Size of image in bytes + * @offset: Offset of the image in the FIT (0=none) + * @desc: Description of the iamge (taken from the FIT) + */ +struct upl_image { + ulong load; + ulong size; + uint offset; + const char *description; +}; + +/** + * struct memregion - Information about a region of memory + * + * @base: Base address + * @size: Size in bytes + */ +struct memregion { + ulong base; + ulong size; +}; + +/** + * struct upl_mem - Information about physical-memory layout + * + * TODO: Figure out initial-mapped-area + * + * @region: Memory region list (struct memregion) + * @hotpluggable: true if hotpluggable + */ +struct upl_mem { + struct alist region; + bool hotpluggable; +}; + +/** + * enum upl_usage - Encodes the usage + * + * Each is a bit number from the usage mask + */ +enum upl_usage { + UPLUS_ACPI_RECLAIM, + UPLUS_ACPI_NVS, + UPLUS_BOOT_CODE, + UPLUS_BOOT_DATA, + UPLUS_RUNTIME_CODE, + UPLUS_RUNTIME_DATA, + UPLUS_COUNT +}; + +/** + * struct upl_memmap - Information about logical-memory layout + * + * @name: Node name to use + * @region: Memory region list (struct memregion) + * @usage: Memory-usage mask (enum upl_usage) + */ +struct upl_memmap { + const char *name; + struct alist region; + uint usage; +}; + +/** + * struct upl_memres - Reserved memory + * + * @name: Node name to use + * @region: Reserved memory region list (struct memregion) + * @no_map: true to indicate that a virtual mapping must not be created + */ +struct upl_memres { + const char *name; + struct alist region; + bool no_map; +}; + +enum upl_serial_access_type { + UPLSAT_MMIO, + UPLSAT_IO, +}; + +/* serial defaults */ +enum { + UPLD_REG_IO_SHIFT = 0, + UPLD_REG_OFFSET = 0, + UPLD_REG_IO_WIDTH = 1, +}; + +/** + * enum upl_access_type - Access types + * + * @UPLAT_MMIO: Memory-mapped I/O + * @UPLAT_IO: Separate I/O + */ +enum upl_access_type { + UPLAT_MMIO, + UPLAT_IO, +}; + +/** + * struct upl_serial - Serial console + * + * @compatible: Compatible string (NULL if there is no serial console) + * @clock_frequency: Input clock frequency of UART + * @current_speed: Current baud rate of UART + * @reg: List of base address and size of registers (struct memregion) + * @reg_shift_log2: log2 of distance between each register + * @reg_offset: Offset of registers from the base address + * @reg_width: Register width in bytes + * @virtual_reg: Virtual register access (0 for none) + * @access_type: Register access type to use + */ +struct upl_serial { + const char *compatible; + uint clock_frequency; + uint current_speed; + struct alist reg; + uint reg_io_shift; + uint reg_offset; + uint reg_io_width; + ulong virtual_reg; + enum upl_serial_access_type access_type; +}; + +/** + * enum upl_graphics_format - Graphics formats + * + * @UPLGF_ARGB32: 32bpp format using 0xaarrggbb + * @UPLGF_ABGR32: 32bpp format using 0xaabbggrr + * @UPLGF_ARGB64: 64bpp format using 0xaaaabbbbggggrrrr + */ +enum upl_graphics_format { + UPLGF_ARGB32, + UPLGF_ABGR32, + UPLGF_ABGR64, +}; + +/** + * @reg: List of base address and size of registers (struct memregion) + * @width: Width of display in pixels + * @height: Height of display in pixels + * @stride: Number of bytes from one line to the next + * @format: Pixel format + */ +struct upl_graphics { + struct alist reg; + uint width; + uint height; + uint stride; + enum upl_graphics_format format; +}; + +/* + * Information about the UPL state + * + * @addr_cells: Number of address cells used in the handoff + * @size_cells: Number of size cells used in the handoff + * @bootmode: Boot-mode mask (enum upl_boot_mode) + * @fit: Address of FIT image that was loaded + * @conf_offset: Offset in FIT of the configuration that was selected + * @addr_width: Adress-bus width of machine, e.g. 46 for 46 bits + * @acpi_nvs_size: Size of the ACPI non-volatile-storage area in bytes + * @image: Information about each image (struct upl_image) + * @mem: Information about physical-memory regions (struct upl_mem) + * @nennap: Information about logical-memory regions (struct upl_memmap) + * @nennap: Information about reserved-memory regions (struct upl_memres) + */ +struct upl { + int addr_cells; + int size_cells; + + ulong smbios; + ulong acpi; + uint bootmode; + ulong fit; + uint conf_offset; + uint addr_width; + uint acpi_nvs_size; + + struct alist image; + struct alist mem; + struct alist memmap; + struct alist memres; + struct upl_serial serial; + struct upl_graphics graphics; +}; + +/** + * upl_write_handoff() - Write a Unversal Payload handoff structure + * + * upl: UPL state to write + * @root: root node to write it to + * @skip_existing: Avoid recreating any nodes which already exist in the + * devicetree. For example, if there is a serial node, just leave it alone, + * since don't need to create a new one + * Return: 0 on success, -ve on error + */ +int upl_write_handoff(const struct upl *upl, ofnode root, bool skip_existing); + +/** + * upl_create_handoff_tree() - Write a Unversal Payload handoff structure + * + * upl: UPL state to write + * @treep: Returns a new tree containing the handoff + * Return: 0 on success, -ve on error + */ +int upl_create_handoff_tree(const struct upl *upl, oftree *treep); + +/** + * upl_read_handoff() - Read a Unversal Payload handoff structure + * + * upl: UPL state to read into + * @tree: Devicetree containing the data to read + * Return: 0 on success, -ve on error + */ +int upl_read_handoff(struct upl *upl, oftree tree); + +/** + * upl_get_test_data() - Fill a UPL with some test data + * + * @uts: Test state (can be uninited) + * @upl: Returns test data + * Return: 0 on success, 1 on error + */ +int upl_get_test_data(struct unit_test_state *uts, struct upl *upl); +#endif /* USE_HOSTCC */ + +#if CONFIG_IS_ENABLED(UPL) && defined(CONFIG_XPL_BUILD) + +/** + * upl_set_fit_info() - Set up basic info about the FIT + * + * @fit: Address of FIT + * @conf_offset: Configuration node being used + * @entry_addr: Entry address for next phase + */ +void upl_set_fit_info(ulong fit, int conf_offset, ulong entry_addr); + +/** + * upl_set_fit_addr() - Set up the address of the FIT + * + * @fit: Address of FIT + */ +void upl_set_fit_addr(ulong fit); + +#else +static inline void upl_set_fit_addr(ulong fit) {} +static inline void upl_set_fit_info(ulong fit, int conf_offset, + ulong entry_addr) {} +#endif /* UPL && SPL */ + +/** + * _upl_add_image() - Internal function to add a new image to the UPL + * + * @node: Image node offset in FIT + * @load_addr: Address to which images was loaded + * @size: Image size in bytes + * @desc: Description of image + * Return: 0 if OK, -ENOMEM if out of memory + */ +int _upl_add_image(int node, ulong load_addr, ulong size, const char *desc); + +/** + * upl_add_image() - Add a new image to the UPL + * + * @fit: Pointer to FIT + * @node: Image node offset in FIT + * @load_addr: Address to which images was loaded + * @size: Image size in bytes + * Return: 0 if OK, -ENOMEM if out of memory + */ +static inline int upl_add_image(const void *fit, int node, ulong load_addr, + ulong size) +{ + if (CONFIG_IS_ENABLED(UPL) && IS_ENABLED(CONFIG_XPL_BUILD)) { + const char *desc = fdt_getprop(fit, node, FIT_DESC_PROP, NULL); + + return _upl_add_image(node, load_addr, size, desc); + } + + return 0; +} + +/** upl_init() - Set up a UPL struct */ +void upl_init(struct upl *upl); + +#endif /* __UPL_WRITE_H */ |