aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2025-01-22 16:08:34 -0600
committerTom Rini <trini@konsulko.com>2025-01-22 17:08:47 -0600
commita3b71cc6f5cc74d4edc5808790a3d2999ea3f7fe (patch)
treebf148f9145392c695ffb623ef8c307a4a3fe8e82 /drivers
parent2eed5a1ff36217372e19f7513bd07077fc76718a (diff)
parent8985ff56b16dc6c04da2c96d48e7f6f54d04e3ff (diff)
downloadu-boot-a3b71cc6f5cc74d4edc5808790a3d2999ea3f7fe.tar.gz
Merge patch series "upl: Prerequite patches for updated spec"
Simon Glass <sjg@chromium.org> says: The current UPL spec[1] has been tidied up and improved over the last year, since U-Boot's original UPL support was written. This series includes some prerequisite patches needed for the real UPL patches. It is split from [2] [1] https://github.com/UniversalPayload/spec/tree/3f1450d [2] https://patchwork.ozlabs.org/project/uboot/list/?series=438574&state=* Link: https://lore.kernel.org/r/20250111000029.245022-1-sjg@chromium.org
Diffstat (limited to 'drivers')
-rw-r--r--drivers/core/ofnode.c67
-rw-r--r--drivers/misc/qfw_acpi.c37
-rw-r--r--drivers/misc/qfw_smbios.c45
-rw-r--r--drivers/pci/pci_rom.c3
-rw-r--r--drivers/serial/ns16550.c2
-rw-r--r--drivers/video/bochs.c1
-rw-r--r--drivers/video/video-uclass.c1
7 files changed, 117 insertions, 39 deletions
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index c8161827d1c..26e014d5c53 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -118,7 +118,7 @@ int oftree_new(oftree *treep)
return log_msg_ret("liv", ret);
tree = oftree_from_np(root);
} else {
- const int size = 1024;
+ const int size = 4096;
void *fdt;
ret = check_tree_count();
@@ -309,6 +309,29 @@ bool ofnode_name_eq(ofnode node, const char *name)
return (strlen(name) == len) && !strncmp(node_name, name, len);
}
+bool ofnode_name_eq_unit(ofnode node, const char *name)
+{
+ const char *node_name, *p;
+ int len;
+
+ assert(ofnode_valid(node));
+
+ node_name = ofnode_get_name(node);
+
+ /* check the whole name */
+ if (!strcmp(node_name, name))
+ return true;
+
+ /* if @name has no unit address, try the node name without it */
+ len = strlen(name);
+ p = strchr(node_name, '@');
+ if (p && !strchr(name, '@') && len == p - node_name &&
+ !strncmp(node_name, name, len))
+ return true;
+
+ return false;
+}
+
int ofnode_read_u8(ofnode node, const char *propname, u8 *outp)
{
const u8 *cell;
@@ -576,14 +599,9 @@ ofnode ofnode_find_subnode(ofnode node, const char *subnode_name)
log_debug("%s: %s: ", __func__, subnode_name);
if (ofnode_is_np(node)) {
- struct device_node *np = ofnode_to_np(node);
-
- for (np = np->child; np; np = np->sibling) {
- if (!strcmp(subnode_name, np->name))
- break;
- }
- subnode = np_to_ofnode(np);
+ subnode = ofnode_find_subnode_unit(node, subnode_name);
} else {
+ /* special case to avoid code-size increase */
int ooffset = fdt_subnode_offset(ofnode_to_fdt(node),
ofnode_to_offset(node), subnode_name);
subnode = noffset_to_ofnode(node, ooffset);
@@ -594,6 +612,26 @@ ofnode ofnode_find_subnode(ofnode node, const char *subnode_name)
return subnode;
}
+ofnode ofnode_find_subnode_unit(ofnode node, const char *subnode_name)
+{
+ ofnode subnode, found = ofnode_null();
+
+ assert(ofnode_valid(node));
+ log_debug("%s: ", subnode_name);
+
+ ofnode_for_each_subnode(subnode, node) {
+ if (ofnode_name_eq_unit(subnode, subnode_name)) {
+ found = subnode;
+ break;
+ }
+ }
+
+ log_debug("%s\n", ofnode_valid(found) ?
+ ofnode_get_name(found) : "<none>");
+
+ return found;
+}
+
int ofnode_read_u32_array(ofnode node, const char *propname,
u32 *out_values, size_t sz)
{
@@ -1710,9 +1748,10 @@ ofnode ofnode_by_prop_value(ofnode from, const char *propname,
int ofnode_write_prop(ofnode node, const char *propname, const void *value,
int len, bool copy)
{
+ int ret;
+
if (of_live_active()) {
void *newval;
- int ret;
if (copy) {
newval = malloc(len);
@@ -1726,8 +1765,12 @@ int ofnode_write_prop(ofnode node, const char *propname, const void *value,
free(newval);
return ret;
} else {
- return fdt_setprop(ofnode_to_fdt(node), ofnode_to_offset(node),
- propname, value, len);
+ ret = fdt_setprop(ofnode_to_fdt(node), ofnode_to_offset(node),
+ propname, value, len);
+ if (ret)
+ return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EINVAL;
+
+ return 0;
}
}
@@ -2015,7 +2058,7 @@ int ofnode_add_subnode(ofnode node, const char *name, ofnode *subnodep)
ret = -EEXIST;
}
if (offset < 0)
- return -EINVAL;
+ return offset == -FDT_ERR_NOSPACE ? -ENOSPC : -EINVAL;
subnode = noffset_to_ofnode(node, offset);
}
diff --git a/drivers/misc/qfw_acpi.c b/drivers/misc/qfw_acpi.c
index 7ffed1e8c02..0d0cf764689 100644
--- a/drivers/misc/qfw_acpi.c
+++ b/drivers/misc/qfw_acpi.c
@@ -7,6 +7,7 @@
#define LOG_CATEGORY UCLASS_QFW
#include <acpi/acpi_table.h>
+#include <bloblist.h>
#include <errno.h>
#include <malloc.h>
#include <mapmem.h>
@@ -160,6 +161,15 @@ ulong write_acpi_tables(ulong addr)
struct bios_linker_entry *entry;
uint32_t size;
struct udevice *dev;
+ struct acpi_ctx *ctx;
+
+ ctx = malloc(sizeof(*ctx));
+ if (!ctx) {
+ printf("error: out of memory for acpi ctx\n");
+ return addr;
+ }
+
+ acpi_setup_ctx(ctx, addr);
ret = qfw_get_dev(&dev);
if (ret) {
@@ -257,6 +267,29 @@ ulong acpi_get_rsdp_addr(void)
return file->addr;
}
+void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt,
+ struct acpi_xsdt *xsdt)
+{
+ memset(rsdp, 0, sizeof(struct acpi_rsdp));
+
+ memcpy(rsdp->signature, RSDP_SIG, 8);
+ memcpy(rsdp->oem_id, OEM_ID, 6);
+
+ if (rsdt)
+ rsdp->rsdt_address = nomap_to_sysmem(rsdt);
+
+ if (xsdt)
+ rsdp->xsdt_address = nomap_to_sysmem(xsdt);
+
+ rsdp->length = sizeof(struct acpi_rsdp);
+ rsdp->revision = ACPI_RSDP_REV_ACPI_2_0;
+
+ /* Calculate checksums */
+ rsdp->checksum = table_compute_checksum(rsdp, 20);
+ rsdp->ext_checksum = table_compute_checksum(rsdp,
+ sizeof(struct acpi_rsdp));
+}
+
#ifndef CONFIG_X86
static int evt_write_acpi_tables(void)
{
@@ -264,9 +297,9 @@ static int evt_write_acpi_tables(void)
void *ptr;
/* Reserve 64K for ACPI tables, aligned to a 4K boundary */
- ptr = memalign(SZ_4K, SZ_64K);
+ ptr = bloblist_add(BLOBLISTT_ACPI_TABLES, SZ_64K, 12);
if (!ptr)
- return -ENOMEM;
+ return -ENOBUFS;
addr = map_to_sysmem(ptr);
/* Generate ACPI tables */
diff --git a/drivers/misc/qfw_smbios.c b/drivers/misc/qfw_smbios.c
index c3e8c310d00..93c4a80286b 100644
--- a/drivers/misc/qfw_smbios.c
+++ b/drivers/misc/qfw_smbios.c
@@ -5,6 +5,7 @@
#define LOG_CATEGORY UCLASS_QFW
+#include <bloblist.h>
#include <efi_loader.h>
#include <errno.h>
#include <log.h>
@@ -15,6 +16,7 @@
#include <tables_csum.h>
#include <linux/sizes.h>
#include <asm/global_data.h>
+#include <linux/err.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -105,11 +107,10 @@ out:
/**
* qfw_write_smbios_tables() - copy SMBIOS tables from QEMU
*
- * @addr: target buffer
- * @size: size of target buffer
+ * @addr: address of target buffer
* Return: 0 for success, -ve on error
*/
-static int qfw_write_smbios_tables(u8 *addr, uint32_t size)
+ulong write_smbios_table(ulong addr)
{
int ret;
struct udevice *dev;
@@ -143,16 +144,13 @@ static int qfw_write_smbios_tables(u8 *addr, uint32_t size)
table = qfw_load_smbios_table(dev, &table_size,
"etc/smbios/smbios-tables");
- if (table_size + sizeof(struct smbios3_entry) > size) {
- free(table);
- return -ENOMEM;
- }
- memcpy(addr, table, table_size);
+ memcpy((void *)addr, table, table_size);
free(table);
- return 0;
+ return addr + table_size;
}
+#ifndef CONFIG_X86
/**
* qfw_evt_write_smbios_tables() - event handler for copying QEMU SMBIOS tables
*
@@ -160,9 +158,9 @@ static int qfw_write_smbios_tables(u8 *addr, uint32_t size)
*/
static int qfw_evt_write_smbios_tables(void)
{
- phys_addr_t addr;
+ ulong addr, end;
void *ptr;
- int ret;
+
/*
* TODO:
* This size is currently hard coded in lib/efi_loader/efi_smbios.c.
@@ -170,22 +168,21 @@ static int qfw_evt_write_smbios_tables(void)
*/
uint32_t size = SZ_4K;
- /* Reserve 64K for SMBIOS tables, aligned to a 4K boundary */
- ptr = memalign(SZ_4K, size);
- if (!ptr) {
- log_err("Out of memory\n");
- return -ENOMEM;
- }
+ log_debug("qfw_evt_write_smbios_tables bloblist\n");
+ /* Reserve 4K for SMBIOS tables, aligned to a 4K boundary */
+ ptr = bloblist_add(BLOBLISTT_SMBIOS_TABLES, size, 12);
+ if (!ptr)
+ return log_msg_ret("bloblist", -ENOBUFS);
+
addr = map_to_sysmem(ptr);
/* Generate SMBIOS tables */
- ret = qfw_write_smbios_tables(ptr, size);
- if (ret) {
- if (CONFIG_IS_ENABLED(GENERATE_SMBIOS_TABLE)) {
- log_info("Falling back to U-Boot generated SMBIOS tables\n");
- write_smbios_table(addr);
- }
+ end = write_smbios_table(addr);
+ if (IS_ERR_VALUE(end)) {
+ log_warning("SMBIOS: Failed to write (err=%dE)\n", (int)end);
} else {
+ if (end - addr > size)
+ return -ENOMEM;
log_debug("SMBIOS tables copied from QEMU\n");
}
@@ -193,5 +190,5 @@ static int qfw_evt_write_smbios_tables(void)
return 0;
}
-
EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, qfw_evt_write_smbios_tables);
+#endif /* !X86 */
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c
index 2753df275ca..3697ad00be2 100644
--- a/drivers/pci/pci_rom.c
+++ b/drivers/pci/pci_rom.c
@@ -347,6 +347,7 @@ int vesa_setup_video_priv(struct vesa_mode_info *vesa, u64 fb,
case 32:
case 24:
uc_priv->bpix = VIDEO_BPP32;
+ uc_priv->format = VIDEO_X8B8G8R8;
break;
case 16:
uc_priv->bpix = VIDEO_BPP16;
@@ -392,6 +393,7 @@ int vesa_setup_video(struct udevice *dev, int (*int15_handler)(void))
uc_priv->ysize = ho->ysize;
uc_priv->line_length = ho->line_length;
uc_priv->bpix = ho->bpix;
+ uc_priv->format = ho->format;
} else {
bootstage_start(BOOTSTAGE_ID_ACCUM_LCD, "vesa display");
ret = dm_pci_run_vga_bios(dev, int15_handler,
@@ -438,6 +440,7 @@ int vesa_setup_video(struct udevice *dev, int (*int15_handler)(void))
ho->ysize = uc_priv->ysize;
ho->line_length = uc_priv->line_length;
ho->bpix = uc_priv->bpix;
+ ho->format = uc_priv->format;
}
return 0;
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index c3b884b6d00..039da835f5f 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -464,7 +464,7 @@ int ns16550_serial_getinfo(struct udevice *dev, struct serial_device_info *info)
struct ns16550_plat *plat = com_port->plat;
/* save code size */
- if (!not_xpl())
+ if (!not_xpl() && !CONFIG_IS_ENABLED(UPL_OUT))
return -ENOSYS;
info->type = SERIAL_CHIP_16550_COMPATIBLE;
diff --git a/drivers/video/bochs.c b/drivers/video/bochs.c
index 00e673a4db0..c34bc23f274 100644
--- a/drivers/video/bochs.c
+++ b/drivers/video/bochs.c
@@ -64,6 +64,7 @@ static int bochs_init_fb(struct udevice *dev)
uc_priv->xsize = xsize;
uc_priv->ysize = ysize;
uc_priv->bpix = VIDEO_BPP32;
+ uc_priv->format = VIDEO_X8B8G8R8;
/* setup video mode */
bochs_write(mmio, INDEX_ENABLE, 0);
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index a5b3e898066..ff4f2199585 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -589,6 +589,7 @@ static int video_post_probe(struct udevice *dev)
ho->ysize = priv->ysize;
ho->line_length = priv->line_length;
ho->bpix = priv->bpix;
+ ho->format = priv->format;
}
if (IS_ENABLED(CONFIG_VIDEO_COPY) && plat->copy_base)