Change fdt-specific loader into a generic setup_data loader
authorH. Peter Anvin <hpa@linux.intel.com>
Fri, 29 Jun 2012 22:16:03 +0000 (15:16 -0700)
committerH. Peter Anvin <hpa@linux.intel.com>
Fri, 29 Jun 2012 22:16:03 +0000 (15:16 -0700)
Make it a generic setup_data loader keyed by type.

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Cc: Thierry Reding <thierry.reding@avionic-design.de>
com32/include/syslinux/linux.h
com32/lib/Makefile
com32/lib/syslinux/fdt.c [deleted file]
com32/lib/syslinux/load_linux.c
com32/lib/syslinux/setup_data.c [new file with mode: 0644]
com32/modules/linux.c

index 6a5c2db..22ee5d5 100644 (file)
@@ -51,17 +51,16 @@ struct initramfs {
 };
 #define INITRAMFS_MAX_ALIGN    4096
 
-struct fdt {
-       void *data;
-       size_t len;
-};
-#define DEVICETREE_MAX_ALIGN   4096
-
-struct setup_data {
+struct setup_data_header {
        uint64_t next;
        uint32_t type;
        uint32_t len;
-       uint8_t data[0];
+} __packed;
+
+struct setup_data {
+    struct setup_data *prev, *next;
+    const void *data;
+    struct setup_data_header hdr;
 };
 
 #define SETUP_NONE     0
@@ -69,7 +68,8 @@ struct setup_data {
 #define SETUP_DTB      2
 
 int syslinux_boot_linux(void *kernel_buf, size_t kernel_size,
-                       struct initramfs *initramfs, struct fdt *fdt,
+                       struct initramfs *initramfs,
+                       struct setup_data *setup_data,
                        char *cmdline);
 
 /* Initramfs manipulation functions */
@@ -88,9 +88,11 @@ int initramfs_load_file(struct initramfs *ihead, const char *src_filename,
 int initramfs_add_trailer(struct initramfs *ihead);
 int initramfs_load_archive(struct initramfs *ihead, const char *filename);
 
-/* Device Tree manipulation functions */
+/* Setup data manipulation functions */
 
-struct fdt *fdt_init(void);
-int fdt_load(struct fdt *fdt, const char *filename);
+int setup_data_add(struct setup_data *head, uint32_t type,
+                  const void *data, size_t data_len);
+int setup_data_load(struct setup_data *head, uint32_t type,
+                   const char *filename);
 
 #endif /* _SYSLINUX_LINUX_H */
index a4959f6..5ab1fac 100644 (file)
@@ -131,7 +131,7 @@ LIBOBJS = \
        \
        syslinux/disk.o                                                 \
        \
-       syslinux/fdt.o
+       syslinux/setup_data.o
 
 # These are the objects which are also imported into the core
 LIBCOREOBJS =  \
diff --git a/com32/lib/syslinux/fdt.c b/com32/lib/syslinux/fdt.c
deleted file mode 100644 (file)
index 1bcd90b..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <stdlib.h>
-#include <syslinux/linux.h>
-#include <syslinux/loadfile.h>
-
-struct fdt *fdt_init(void)
-{
-       struct fdt *fdt;
-
-       fdt = calloc(1, sizeof(*fdt));
-       if (!fdt)
-               return NULL;
-
-       return fdt;
-}
-
-int fdt_load(struct fdt *fdt, const char *filename)
-{
-       void *data;
-       size_t len;
-
-       if (loadfile(filename, &data, &len))
-               return -1;
-
-       fdt->data = data;
-       fdt->len = len;
-
-       return 0;
-}
index b68aef7..86fc07f 100644 (file)
@@ -180,7 +180,8 @@ static int map_initramfs(struct syslinux_movelist **fraglist,
 }
 
 int syslinux_boot_linux(void *kernel_buf, size_t kernel_size,
-                       struct initramfs *initramfs, struct fdt *fdt,
+                       struct initramfs *initramfs,
+                       struct setup_data *setup_data,
                        char *cmdline)
 {
     struct linux_header hdr, *whdr;
@@ -188,6 +189,7 @@ int syslinux_boot_linux(void *kernel_buf, size_t kernel_size,
     addr_t real_mode_base, prot_mode_base;
     addr_t irf_size;
     size_t cmdline_size, cmdline_offset;
+    struct setup_data *sdp;
     struct syslinux_rm_regs regs;
     struct syslinux_movelist *fraglist = NULL;
     struct syslinux_memmap *mmap = NULL;
@@ -450,42 +452,41 @@ int syslinux_boot_linux(void *kernel_buf, size_t kernel_size,
        }
     }
 
-    if (fdt && fdt->len > 0) {
-       const addr_t align_mask = DEVICETREE_MAX_ALIGN - 1;
-       struct syslinux_memmap *ml;
-       struct setup_data *setup;
-       addr_t best_addr = 0;
-       size_t size;
+    if (setup_data) {
+       uint64_t *prev_ptr = &whdr->setup_data;
 
-       size = sizeof(*setup) + fdt->len;
-
-       setup = malloc(size);
-       if (!setup)
-               goto bail;
+       for (sdp = setup_data->next; sdp != setup_data; sdp = sdp->next) {
+           struct syslinux_memmap *ml;
+           const addr_t align_mask = 15; /* Header is 16 bytes */
+           addr_t best_addr = 0;
+           size_t size = sdp->hdr.len + sizeof(sdp->hdr);
 
-       setup->next = 0;
-       setup->type = SETUP_DTB;
-       setup->len = fdt->len;
-       memcpy(setup->data, fdt->data, fdt->len);
+           if (!sdp->data || !sdp->hdr.len)
+               continue;
 
-       for (ml = amap; ml->type != SMT_END; ml = ml->next) {
+           for (ml = amap; ml->type != SMT_END; ml = ml->next) {
                addr_t adj_start = (ml->start + align_mask) & ~align_mask;
                addr_t adj_end = ml->next->start & ~align_mask;
 
                if (ml->type == SMT_FREE && adj_end - adj_start >= size)
-                       best_addr = (adj_end - size) & ~align_mask;
-       }
+                   best_addr = (adj_end - size) & ~align_mask;
+           }
 
-       if (!best_addr)
+           if (!best_addr)
                goto bail;
 
-       whdr->setup_data = best_addr;
-
-       if (syslinux_add_memmap(&amap, best_addr, size, SMT_ALLOC))
-           goto bail;
+           *prev_ptr = best_addr;
+           prev_ptr = &sdp->hdr.next;
 
-       if (syslinux_add_movelist(&fraglist, best_addr, (addr_t) setup, size))
-           goto bail;
+           if (syslinux_add_memmap(&amap, best_addr, size, SMT_ALLOC))
+               goto bail;
+           if (syslinux_add_movelist(&fraglist, best_addr,
+                                     (addr_t)&sdp->hdr, sizeof sdp->hdr))
+               goto bail;
+           if (syslinux_add_movelist(&fraglist, best_addr + sizeof sdp->hdr,
+                                     (addr_t)sdp->data, sdp->hdr.len))
+               goto bail;
+       }
     }
 
     /* Set up the registers on entry */
diff --git a/com32/lib/syslinux/setup_data.c b/com32/lib/syslinux/setup_data.c
new file mode 100644 (file)
index 0000000..a36c5b6
--- /dev/null
@@ -0,0 +1,47 @@
+#include <stdlib.h>
+#include <syslinux/linux.h>
+#include <syslinux/loadfile.h>
+
+struct setup_data *setup_data_init(void)
+{
+    struct setup_data *setup_data;
+
+    setup_data = zalloc(sizeof(*setup_data));
+    if (!setup_data)
+       return NULL;
+
+    setup_data->prev = setup_data->next = setup_data;
+    return setup_data;
+}
+
+int setup_data_add(struct setup_data *head, uint32_t type,
+                  const void *data, size_t data_len)
+{
+       struct setup_data *setup_data;
+
+       setup_data = zalloc(sizeof(*setup_data));
+       if (!setup_data)
+           return -1;
+
+       setup_data->data     = data;
+       setup_data->hdr.len  = data_len;
+       setup_data->hdr.type = type;
+       setup_data->prev     = head->prev;
+       setup_data->next     = head;
+       head->prev->next     = setup_data;
+       head->prev           = setup_data;
+
+       return 0;
+}
+
+int setup_data_load(struct setup_data *head, uint32_t type,
+                   const char *filename)
+{
+       void *data;
+       size_t len;
+
+       if (loadfile(filename, &data, &len))
+               return -1;
+
+       return setup_data_add(head, type, data, len);
+}
index 679996c..102e877 100644 (file)
@@ -224,7 +224,7 @@ int main(int argc, char *argv[])
 
     /* This should not return... */
     errno = 0;
-    syslinux_boot_linux(kernel_data, kernel_len, initramfs, cmdline);
+    syslinux_boot_linux(kernel_data, kernel_len, initramfs, NULL, cmdline);
     fprintf(stderr, "syslinux_boot_linux() failed: ");
 
 bail: