aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2012-06-29 15:16:03 -0700
committerH. Peter Anvin <hpa@linux.intel.com>2012-06-29 15:16:03 -0700
commit443ce2a3ac055b4ec13f86a782a04be8453fd393 (patch)
tree191c2b8836fcc89b0dd11ebcb871556188cd09ad
parent1eb311caecf1452a78013640db828fd40c9055d2 (diff)
downloadsyslinux-443ce2a3ac055b4ec13f86a782a04be8453fd393.tar.gz
syslinux-443ce2a3ac055b4ec13f86a782a04be8453fd393.tar.xz
syslinux-443ce2a3ac055b4ec13f86a782a04be8453fd393.zip
Change fdt-specific loader into a generic setup_data loader
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>
-rw-r--r--com32/include/syslinux/linux.h26
-rw-r--r--com32/lib/Makefile2
-rw-r--r--com32/lib/syslinux/fdt.c28
-rw-r--r--com32/lib/syslinux/load_linux.c53
-rw-r--r--com32/lib/syslinux/setup_data.c47
-rw-r--r--com32/modules/linux.c2
6 files changed, 90 insertions, 68 deletions
diff --git a/com32/include/syslinux/linux.h b/com32/include/syslinux/linux.h
index 6a5c2dbb..22ee5d55 100644
--- a/com32/include/syslinux/linux.h
+++ b/com32/include/syslinux/linux.h
@@ -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 */
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index a4959f6f..5ab1fac4 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -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
index 1bcd90b9..00000000
--- a/com32/lib/syslinux/fdt.c
+++ /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;
-}
diff --git a/com32/lib/syslinux/load_linux.c b/com32/lib/syslinux/load_linux.c
index b68aef7b..86fc07f8 100644
--- a/com32/lib/syslinux/load_linux.c
+++ b/com32/lib/syslinux/load_linux.c
@@ -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
index 00000000..a36c5b61
--- /dev/null
+++ b/com32/lib/syslinux/setup_data.c
@@ -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);
+}
diff --git a/com32/modules/linux.c b/com32/modules/linux.c
index 679996ce..102e8777 100644
--- a/com32/modules/linux.c
+++ b/com32/modules/linux.c
@@ -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: