From 443ce2a3ac055b4ec13f86a782a04be8453fd393 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 29 Jun 2012 15:16:03 -0700 Subject: [PATCH] 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 Cc: Thierry Reding --- com32/include/syslinux/linux.h | 26 ++++++++++---------- com32/lib/Makefile | 2 +- com32/lib/syslinux/fdt.c | 28 ---------------------- com32/lib/syslinux/load_linux.c | 53 +++++++++++++++++++++-------------------- com32/lib/syslinux/setup_data.c | 47 ++++++++++++++++++++++++++++++++++++ com32/modules/linux.c | 2 +- 6 files changed, 90 insertions(+), 68 deletions(-) delete mode 100644 com32/lib/syslinux/fdt.c create mode 100644 com32/lib/syslinux/setup_data.c diff --git a/com32/include/syslinux/linux.h b/com32/include/syslinux/linux.h index 6a5c2db..22ee5d5 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 a4959f6..5ab1fac 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 1bcd90b..0000000 --- a/com32/lib/syslinux/fdt.c +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include -#include - -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 b68aef7..86fc07f 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 0000000..a36c5b6 --- /dev/null +++ b/com32/lib/syslinux/setup_data.c @@ -0,0 +1,47 @@ +#include +#include +#include + +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 679996c..102e877 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: -- 2.7.4