summaryrefslogtreecommitdiffstats
path: root/sys/boot/uboot/common
diff options
context:
space:
mode:
authorraj <raj@FreeBSD.org>2010-05-25 15:21:39 +0000
committerraj <raj@FreeBSD.org>2010-05-25 15:21:39 +0000
commit4dbde3c9b95a26e2577ac32058a85c7277d419f2 (patch)
tree083efe2b44c3dccb2f0a01c264ccfd3af3ca0af5 /sys/boot/uboot/common
parent08c219d72b905839e115a4a5bbea2f884fbfa970 (diff)
downloadFreeBSD-src-4dbde3c9b95a26e2577ac32058a85c7277d419f2.zip
FreeBSD-src-4dbde3c9b95a26e2577ac32058a85c7277d419f2.tar.gz
Initial loader(8) support for Flattened Device Tree.
o This is disabled by default for now, and can be enabled using WITH_FDT at build time. o Tested with ARM and PowerPC. Reviewed by: imp Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'sys/boot/uboot/common')
-rw-r--r--sys/boot/uboot/common/main.c21
-rw-r--r--sys/boot/uboot/common/metadata.c48
2 files changed, 60 insertions, 9 deletions
diff --git a/sys/boot/uboot/common/main.c b/sys/boot/uboot/common/main.c
index 6c6a623..7e961fd 100644
--- a/sys/boot/uboot/common/main.c
+++ b/sys/boot/uboot/common/main.c
@@ -53,6 +53,10 @@ extern unsigned char __sbss_start[];
extern unsigned char __sbss_end[];
extern unsigned char _end[];
+#ifdef LOADER_FDT_SUPPORT
+extern int command_fdt_internal(int argc, char *argv[]);
+#endif
+
static void
dump_sig(struct api_signature *sig)
{
@@ -271,3 +275,20 @@ command_sysinfo(int argc, char *argv[])
ub_dump_si(si);
return (CMD_OK);
}
+
+#ifdef LOADER_FDT_SUPPORT
+/*
+ * Since proper fdt command handling function is defined in fdt_loader_cmd.c,
+ * and declaring it as extern is in contradiction with COMMAND_SET() macro
+ * (which uses static pointer), we're defining wrapper function, which
+ * calls the proper fdt handling routine.
+ */
+static int
+command_fdt(int argc, char *argv[])
+{
+
+ return (command_fdt_internal(argc, argv));
+}
+
+COMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt);
+#endif
diff --git a/sys/boot/uboot/common/metadata.c b/sys/boot/uboot/common/metadata.c
index e5f4b04..ec5e219 100644
--- a/sys/boot/uboot/common/metadata.c
+++ b/sys/boot/uboot/common/metadata.c
@@ -42,6 +42,10 @@ __FBSDID("$FreeBSD$");
#include "bootstrap.h"
#include "glue.h"
+#if defined(LOADER_FDT_SUPPORT)
+extern int fdt_fixup(void);
+#endif
+
/*
* Return a 'boothowto' value corresponding to the kernel arguments in
* (kargs) and any relevant environment variables.
@@ -253,6 +257,7 @@ md_copymodules(vm_offset_t addr)
return(addr);
}
+#if !defined(LOADER_FDT_SUPPORT)
/*
* Prepare the bootinfo structure. Put a ptr to the allocated struct in addr,
* return size.
@@ -358,9 +363,10 @@ md_bootinfo(struct bootinfo **addr)
return (size);
}
+#endif
/*
- * Load the information expected by a powerpc kernel.
+ * Load the information expected by a kernel.
*
* - The 'boothowto' argument is constructed
* - The 'bootdev' argument is constructed
@@ -370,7 +376,7 @@ md_bootinfo(struct bootinfo **addr)
int
md_load(char *args, vm_offset_t *modulep)
{
- struct preloaded_file *kfp;
+ struct preloaded_file *kfp, *bfp;
struct preloaded_file *xp;
struct file_metadata *md;
struct bootinfo *bip;
@@ -379,6 +385,7 @@ md_load(char *args, vm_offset_t *modulep)
vm_offset_t envp;
vm_offset_t size;
vm_offset_t vaddr;
+ vm_offset_t dtbp;
char *rootdevname;
int howto;
int bisize;
@@ -389,7 +396,11 @@ md_load(char *args, vm_offset_t *modulep)
* relocation.
*/
uint32_t mdt[] = {
- MODINFOMD_SSYM, MODINFOMD_ESYM, MODINFOMD_KERNEND, MODINFOMD_ENVP
+ MODINFOMD_SSYM, MODINFOMD_ESYM, MODINFOMD_KERNEND,
+ MODINFOMD_ENVP,
+#if defined(LOADER_FDT_SUPPORT)
+ MODINFOMD_DTBP
+#endif
};
howto = md_getboothowto(args);
@@ -405,24 +416,26 @@ md_load(char *args, vm_offset_t *modulep)
/* Try reading the /etc/fstab file to select the root device */
getrootmount(rootdevname);
- /* find the last module in the chain */
+ /* Find the last module in the chain */
addr = 0;
for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) {
if (addr < (xp->f_addr + xp->f_size))
addr = xp->f_addr + xp->f_size;
}
- /* pad to a page boundary */
+ /* Pad to a page boundary */
addr = roundup(addr, PAGE_SIZE);
- /* copy our environment */
+ /* Copy our environment */
envp = addr;
addr = md_copyenv(addr);
- /* pad to a page boundary */
+ /* Pad to a page boundary */
addr = roundup(addr, PAGE_SIZE);
+#if !defined(LOADER_FDT_SUPPORT)
/* prepare bootinfo */
bisize = md_bootinfo(&bip);
+#endif
kernend = 0;
kfp = file_findfile(NULL, "elf32 kernel");
@@ -431,14 +444,29 @@ md_load(char *args, vm_offset_t *modulep)
if (kfp == NULL)
panic("can't find kernel file");
file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
- file_addmetadata(kfp, MODINFOMD_BOOTINFO, bisize, bip);
file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
+
+#if defined(LOADER_FDT_SUPPORT)
+ /* Handle device tree blob */
+ fdt_fixup();
+ if ((bfp = file_findfile(NULL, "dtb")) == NULL &&
+ (howto & RB_VERBOSE))
+ printf("**WARNING** Booting with no DTB loaded!\n");
+
+ dtbp = bfp == NULL ? 0 : bfp->f_addr;
+ file_addmetadata(kfp, MODINFOMD_DTBP, sizeof dtbp, &dtbp);
+#else
+ file_addmetadata(kfp, MODINFOMD_BOOTINFO, bisize, bip);
+#endif
+
file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);
+ /* Figure out the size and location of the metadata */
*modulep = addr;
size = md_copymodules(0);
kernend = roundup(addr + size, PAGE_SIZE);
+ /* Provide MODINFOMD_KERNEND */
md = file_findmetadata(kfp, MODINFOMD_KERNEND);
bcopy(&kernend, md->md_data, sizeof kernend);
@@ -453,7 +481,9 @@ md_load(char *args, vm_offset_t *modulep)
bcopy(&vaddr, md->md_data, sizeof vaddr);
}
}
+
+ /* Only now copy actual modules and metadata */
(void)md_copymodules(addr);
- return(0);
+ return (0);
}
OpenPOWER on IntegriCloud