diff options
-rw-r--r-- | com32/include/syslinux/linux.h | 5 | ||||
-rw-r--r-- | com32/lib/syslinux/load_linux.c | 102 | ||||
-rw-r--r-- | com32/mboot/mboot.h | 2 | ||||
-rw-r--r-- | com32/modules/linux.c | 68 |
4 files changed, 99 insertions, 78 deletions
diff --git a/com32/include/syslinux/linux.h b/com32/include/syslinux/linux.h index 463b49f5..0e47721d 100644 --- a/com32/include/syslinux/linux.h +++ b/com32/include/syslinux/linux.h @@ -52,10 +52,7 @@ struct initramfs { #define INITRAMFS_MAX_ALIGN 4096 int syslinux_boot_linux(void *kernel_buf, size_t kernel_size, - struct initramfs *initramfs, - char *cmdline, - uint16_t video_mode, - uint32_t mem_limit); + struct initramfs *initramfs, char *cmdline); /* Initramfs manipulation functions */ diff --git a/com32/lib/syslinux/load_linux.c b/com32/lib/syslinux/load_linux.c index 41ebcb70..6380149e 100644 --- a/com32/lib/syslinux/load_linux.c +++ b/com32/lib/syslinux/load_linux.c @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------- * * * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved - * Copyright 2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -32,6 +32,7 @@ * Load a Linux kernel (Image/zImage/bzImage). */ +#include <ctype.h> #include <stdbool.h> #include <stdlib.h> #include <inttypes.h> @@ -94,6 +95,74 @@ struct linux_header { #define LOAD_HIGH 0x01 #define CAN_USE_HEAP 0x80 +/* Get a value with a potential suffix (k/m/g/t/p/e) */ +static unsigned long long suffix_number(const char *str) +{ + char *ep; + unsigned long long v; + int shift; + + v = strtoull(str, &ep, 0); + switch (*ep|0x20) { + case 'k': + shift = 10; + break; + case 'm': + shift = 20; + break; + case 'g': + shift = 30; + break; + case 't': + shift = 40; + break; + case 'p': + shift = 50; + break; + case 'e': + shift = 60; + break; + default: + shift = 0; + break; + } + v <<= shift; + + return v; +} + +/* + * Find the last instance of a particular command line argument + * (which should include the final =; do not use for boolean arguments) + * Note: the resulting string is typically not null-terminated. + */ +static const char *find_argument(const char *cmdline, const char *argument) +{ + const char *found = NULL; + const char *p = cmdline; + bool was_space = true; + size_t la = strlen(argument); + + while (*p) { + if (isspace(*p)) { + was_space = true; + } else if (was_space) { + if (!memcmp(p, argument, la)) + found = p+la; + was_space = false; + } + p++; + } + + return found; +} + +/* Truncate to 32 bits, with saturate */ +static inline uint32_t saturate32(unsigned long long v) +{ + return (v > 0xffffffff) ? 0xffffffff : (uint32_t)v; +} + /* Get the combined size of the initramfs */ static addr_t initramfs_size(struct initramfs *initramfs) { @@ -148,10 +217,7 @@ static int map_initramfs(struct syslinux_movelist **fraglist, } int syslinux_boot_linux(void *kernel_buf, size_t kernel_size, - struct initramfs *initramfs, - char *cmdline, - uint16_t video_mode, - uint32_t memlimit) + struct initramfs *initramfs, char *cmdline) { struct linux_header hdr, *whdr; size_t real_mode_size, prot_mode_size; @@ -163,12 +229,36 @@ int syslinux_boot_linux(void *kernel_buf, size_t kernel_size, struct syslinux_memmap *mmap = NULL; struct syslinux_memmap *amap = NULL; bool ok; + uint32_t memlimit = 0; + uint16_t video_mode = 0; + const char *arg; cmdline_size = strlen(cmdline)+1; if (kernel_size < 2*512) goto bail; + /* Look for specific command-line arguments we care about */ + if ((arg = find_argument(cmdline, "mem="))) + memlimit = saturate32(suffix_number(arg)); + + if ((arg = find_argument(cmdline, "vga="))) { + switch (arg[0] | 0x20) { + case 'a': /* "ask" */ + video_mode = 0xfffd; + break; + case 'e': /* "ext" */ + video_mode = 0xfffe; + break; + case 'n': /* "normal" */ + video_mode = 0xffff; + break; + default: + video_mode = strtoul(arg, NULL, 0); + break; + } + } + /* Copy the header into private storage */ /* Use whdr to modify the actual kernel header */ memcpy(&hdr, kernel_buf, sizeof hdr); @@ -190,7 +280,7 @@ int syslinux_boot_linux(void *kernel_buf, size_t kernel_size, if (hdr.version < 0x0203) hdr.initrd_addr_max = 0x37ffffff; - if (!memlimit || memlimit-1 > hdr.initrd_addr_max) + if (!memlimit && memlimit-1 > hdr.initrd_addr_max) memlimit = hdr.initrd_addr_max+1; /* Zero for no limit */ if (hdr.version < 0x0205) diff --git a/com32/mboot/mboot.h b/com32/mboot/mboot.h index c05d69f1..c14ed81c 100644 --- a/com32/mboot/mboot.h +++ b/com32/mboot/mboot.h @@ -54,7 +54,7 @@ #include "mb_header.h" #include "mb_info.h" -#define DEBUG 0 +#define DEBUG 1 #if DEBUG # define dprintf printf #else diff --git a/com32/modules/linux.c b/com32/modules/linux.c index a2edd10b..87b610d4 100644 --- a/com32/modules/linux.c +++ b/com32/modules/linux.c @@ -63,48 +63,6 @@ static char *find_argument(char **argv, const char *argument) return ptr; } -/* Get a value with a potential suffix (k/m/g/t/p/e) */ -static unsigned long long suffix_number(const char *str) -{ - char *ep; - unsigned long long v; - int shift; - - v = strtoull(str, &ep, 0); - switch (*ep|0x20) { - case 'k': - shift = 10; - break; - case 'm': - shift = 20; - break; - case 'g': - shift = 30; - break; - case 't': - shift = 40; - break; - case 'p': - shift = 50; - break; - case 'e': - shift = 60; - break; - default: - shift = 0; - break; - } - v <<= shift; - - return v; -} - -/* Truncate to 32 bits, with saturate */ -static inline uint32_t saturate32(unsigned long long v) -{ - return (v > 0xffffffff) ? 0xffffffff : (uint32_t)v; -} - /* Stitch together the command line from a set of argv's */ static char *make_cmdline(char **argv) { @@ -137,8 +95,6 @@ static char *make_cmdline(char **argv) int main(int argc, char *argv[]) { - uint32_t mem_limit = 0; - uint16_t video_mode = 0; const char *kernel_name; struct initramfs *initramfs; char *cmdline; @@ -200,27 +156,6 @@ int main(int argc, char *argv[]) if (!initramfs) goto bail; - /* Look for specific command-line arguments we care about */ - if ((arg = find_argument(argp, "mem="))) - mem_limit = saturate32(suffix_number(arg)); - - if ((arg = find_argument(argp, "vga="))) { - switch (arg[0] | 0x20) { - case 'a': /* "ask" */ - video_mode = 0xfffd; - break; - case 'e': /* "ext" */ - video_mode = 0xfffe; - break; - case 'n': /* "normal" */ - video_mode = 0xffff; - break; - default: - video_mode = strtoul(arg, NULL, 0); - break; - } - } - if ((arg = find_argument(argp, "initrd="))) { do { p = strchr(arg, ','); @@ -248,8 +183,7 @@ int main(int argc, char *argv[]) } /* This should not return... */ - syslinux_boot_linux(kernel_data, kernel_len, initramfs, cmdline, - video_mode, mem_limit); + syslinux_boot_linux(kernel_data, kernel_len, initramfs, cmdline); bail: fprintf(stderr, "Kernel load failure (insufficient memory?)\n"); |