@@ -100,38 +100,9 @@ int dram_init(void)
}
int dram_init_banksize(void)
{
- struct efi_mem_desc *desc, *end;
- struct efi_entry_memmap *map;
- int ret, size;
- int num_banks;
-
- ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
- if (ret) {
- /* We should have stopped in dram_init(), something is wrong */
- debug("%s: Missing memory map\n", __func__);
- return -ENXIO;
- }
- end = (struct efi_mem_desc *)((ulong)map + size);
- desc = map->desc;
- for (num_banks = 0;
- desc < end && num_banks < CONFIG_NR_DRAM_BANKS;
- desc = efi_get_next_mem_desc(desc, map->desc_size)) {
- /*
- * We only use conventional memory and ignore
- * anything less than 1MB.
- */
- if (desc->type != EFI_CONVENTIONAL_MEMORY ||
- (desc->num_pages << EFI_PAGE_SHIFT) < 1 << 20)
- continue;
- gd->bd->bi_dram[num_banks].start = desc->physical_start;
- gd->bd->bi_dram[num_banks].size = desc->num_pages <<
- EFI_PAGE_SHIFT;
- num_banks++;
- }
-
- return 0;
+ return dram_init_banksize_from_efi();
}
int arch_cpu_init(void)
{
@@ -34,5 +34,27 @@ enum efi_entry_t {
* of the requested type, -EPROTONOSUPPORT if the table has the wrong version
*/
int efi_info_get(enum efi_entry_t type, void **datap, int *sizep);
+struct device_node;
+
+/**
+ * of_populate_from_efi() - Populate the live tree from EFI tables
+ *
+ * @root: Root node of tree to populate
+ *
+ * This function populates the live tree with information from EFI tables
+ * it is only applicable when running U-Boot as an EFI payload with
+ * CONFIG_EFI_STUB enabled.
+ */
+int of_populate_from_efi(struct device_node *root);
+
+/**
+ * dram_init_banksize_from_efi() - Initialize the memory banks from EFI tables
+ *
+ * This function initializes the memory banks from the EFI memory map table we
+ * stashed from the EFI stub. It is only applicable when running U-Boot as an
+ * EFI payload with CONFIG_EFI_STUB enabled.
+ */
+int dram_init_banksize_from_efi(void);
+
#endif /* _EFI_STUB_H */
@@ -9,8 +9,13 @@
#include <efi_stub.h>
#include <errno.h>
#include <mapmem.h>
#include <asm/global_data.h>
+#include <efi_api.h>
+#include <dm/of.h>
+#include <dm/ofnode.h>
+#include <dm/of_access.h>
+#include <log.h>
DECLARE_GLOBAL_DATA_PTR;
int efi_info_get(enum efi_entry_t type, void **datap, int *sizep)
@@ -46,4 +51,106 @@ err:
unmap_sysmem(info);
return -ENOSYS;
}
+
+#ifdef CONFIG_OF_LIVE
+static int of_populate_framebuffer(struct device_node *root)
+{
+ struct device_node *chosen, *fb;
+ struct efi_entry_gopmode *mode;
+ ofnode node;
+ int ret, size;
+ u64 reg[2];
+ char fb_node_name[50] = { 0 };
+
+ ret = efi_info_get(EFIET_GOP_MODE, (void **)&mode, &size);
+ if (ret) {
+ printf("EFI graphics output entry not found\n");
+ return ret;
+ }
+
+ fb = of_find_node_opts_by_path(root, "/chosen/framebuffer", NULL);
+ /* framebuffer already defined */
+ if (fb)
+ return 0;
+
+ chosen = of_find_node_opts_by_path(root, "/chosen", NULL);
+ if (!chosen) {
+ ret = of_add_subnode(root, "chosen", -1, &chosen);
+ if (ret) {
+ debug("Failed to add chosen node\n");
+ return ret;
+ }
+ }
+ node = np_to_ofnode(chosen);
+ ofnode_write_u32(node, "#address-cells", 2);
+ ofnode_write_u32(node, "#size-cells", 2);
+ /*
+ * In order for of_translate_one() to correctly detect an empty ranges property, the value
+ * pointer has to be non-null even though the length is 0.
+ */
+ of_write_prop(chosen, "ranges", 0, (void *)FDT_ADDR_T_NONE);
+
+ snprintf(fb_node_name, sizeof(fb_node_name), "framebuffer@%llx", mode->fb_base);
+ ret = of_add_subnode(chosen, fb_node_name, -1, &fb);
+ if (ret) {
+ debug("Failed to add framebuffer node\n");
+ return ret;
+ }
+ node = np_to_ofnode(fb);
+ ofnode_write_string(node, "compatible", "simple-framebuffer");
+ reg[0] = cpu_to_fdt64(mode->fb_base);
+ reg[1] = cpu_to_fdt64(mode->fb_size);
+ ofnode_write_prop(node, "reg", reg, sizeof(reg), true);
+ ofnode_write_u32(node, "width", mode->info->width);
+ ofnode_write_u32(node, "height", mode->info->height);
+ ofnode_write_u32(node, "stride", mode->info->pixels_per_scanline * 4);
+ ofnode_write_string(node, "format", "a8r8g8b8");
+
+ return 0;
+}
+#endif
+
+int of_populate_from_efi(struct device_node *root)
+{
+ int ret = 0;
+
+ if (CONFIG_IS_ENABLED(VIDEO_SIMPLE) && CONFIG_IS_ENABLED(OF_LIVE))
+ ret = of_populate_framebuffer(root);
+
+ return ret;
+}
+
+int dram_init_banksize_from_efi(void)
+{
+ struct efi_mem_desc *desc, *end;
+ struct efi_entry_memmap *map;
+ int ret, size;
+ int num_banks;
+
+ ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
+ if (ret) {
+ /* We should have stopped in dram_init(), something is wrong */
+ debug("%s: Missing memory map\n", __func__);
+ return -ENXIO;
+ }
+ end = (struct efi_mem_desc *)((ulong)map + size);
+ desc = map->desc;
+ for (num_banks = 0;
+ desc < end && num_banks < CONFIG_NR_DRAM_BANKS;
+ desc = efi_get_next_mem_desc(desc, map->desc_size)) {
+ /*
+ * We only use conventional memory and ignore
+ * anything less than 1MB.
+ */
+ if (desc->type != EFI_CONVENTIONAL_MEMORY ||
+ (desc->num_pages << EFI_PAGE_SHIFT) < 1 << 20)
+ continue;
+ gd->bd->bi_dram[num_banks].start = desc->physical_start;
+ gd->bd->bi_dram[num_banks].size = desc->num_pages <<
+ EFI_PAGE_SHIFT;
+ num_banks++;
+ }
+
+ return 0;
+}
@@ -10,8 +10,9 @@
#define LOG_CATEGORY LOGC_DT
#include <abuf.h>
+#include <efi_stub.h>
#include <log.h>
#include <linux/libfdt.h>
#include <of_live.h>
#include <malloc.h>
@@ -334,8 +335,16 @@ int of_live_build(const void *fdt_blob, struct device_node **rootp)
return ret;
}
debug("%s: stop\n", __func__);
+ /*
+ * When booting with EFI_STUB we can automatically generate a framebuffer
+ * node based on the EFI data.
+ */
+ ret = of_populate_from_efi(*rootp);
+ if (ret)
+ debug("Failed to populate live tree nodes from EFI: err=%d\n", ret);
+
return ret;
}
void of_live_free(struct device_node *root)
Introduce two new helpers dram_init_banksize_from_efi() and of_populate_from_efi(). These populate the DRAM bank info and simplefb framebuffer OF node respectively using the EFI table populated by the EFI stub. dram_init_banksize_from_efi() is directly moved from the x86 payload code to make it available for other boards. Populating the simplefb node allows for an easy way to bring up video without the full heft of VIDEO_EFI which is not particularly well-suited to ARM. Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org> --- arch/x86/cpu/efi/payload.c | 31 +------------ include/efi_stub.h | 22 ++++++++++ lib/efi/efi_info.c | 107 +++++++++++++++++++++++++++++++++++++++++++++ lib/of_live.c | 9 ++++ 4 files changed, 139 insertions(+), 30 deletions(-)