Shao Miller
2011-Aug-06 09:43 UTC
[syslinux] [PATCH] ifmemdsk.c32: Allow boot options based on presence of MEMDISK
Below, attached, and available at the 'ifmemdsk' branch at: http://git.zytor.com/?p=users/sha0/syslinux.git;a=commitdiff;h=a975c12919bbd48739fede4ebfe099d98b87192e Review welcome! - Shao Miller ----- From a975c12919bbd48739fede4ebfe099d98b87192e Mon Sep 17 00:00:00 2001 From: Shao Miller <shao.miller at yrdsb.edu.on.ca> Date: Sat, 6 Aug 2011 05:24:46 -0400 Subject: [PATCH] ifmemdsk.c32: Allow boot options based on presence of MEMDISK Like 'ifcpu.c32' and 'ifplop.c32', this COMBOOT32 module will check for the presence of MEMDISK(s) and choose one of two (optionally) specified commands. Signed-off-by: Shao Miller <shao.miller at yrdsb.edu.on.ca> --- NEWS | 1 + com32/modules/ifmemdsk.c | 389 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 390 insertions(+), 0 deletions(-) create mode 100755 com32/modules/ifmemdsk.c diff --git a/NEWS b/NEWS index 88adba1..7700504 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ Changes in 4.05: on virtually all systems since the beginning, and has been totally broken since 4.00 at least. Use MEMDISK instead. * chain.c32: Support chaining ReactOS' FreeLdr (Shao Miller) + * ifmemdsk.c32: Choose boot option based on presence of MEMDISK Changes in 4.04: * PXELINUX: Fix handling of unqualified DNS names. diff --git a/com32/modules/ifmemdsk.c b/com32/modules/ifmemdsk.c new file mode 100755 index 0000000..d36f5ec --- /dev/null +++ b/com32/modules/ifmemdsk.c @@ -0,0 +1,389 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2011 Shao Miller - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/**** + * @file ifmemdsk.c + * + * This COM32 module detects if there are MEMDISKs established. + */ + +static const char usage_text[] = "\ +Usage:\n\ + ifmemdsk.c32 [<option> [...]] --info [<option> [...]]\n\ + ifmemdsk.c32 [<option> [...]] [<detected_cmd>] -- [<not_detected_cmd>]\n\ +\n\ +Options:\n\ + --info . . . . . Displays info about MEMDISK(s)\n\ + --safe-hooks . . Will scan INT 13h \"safe hook\" chain\n\ + --mbfts . . . . . Will scan memory for MEMDISK mBFTs\n\ + --no-sequential Suppresses probing all drive numbers\n\ +\n\ +If a MEMDISK is found, or if a particular MEMDISK is sought by the options\n\ +and is found, then the 'detected_cmd' action will be taken, else the\n\ +'not_detected_cmd' action will be taken.\n\ +\n"; + +#include <stdio.h> +#include <string.h> +#include <alloca.h> +#include <com32.h> +#include <console.h> +#include <syslinux/boot.h> + +/* Pull in MEMDISK common structures */ +#include "../../memdisk/mstructs.h" + +/*** Macros */ +#define M_GET_DRIVE_PARAMS (0x08) +#define M_INT13H ((0x0000 << 4) + 0x0013 * 4) +#define M_FREEBASEMEM ((0x0040 << 4) + 0x0013) +#define M_TOP ((0x9FFF << 4) + 0x0000) + +/*** Object types */ +typedef struct mdi s_mdi; +typedef real_addr_t u_segoff; +typedef struct safe_hook s_safe_hook; +typedef struct mBFT s_mbft; + +/*** Function types */ +typedef int f_find(void); + +/*** Function declarations */ +static const s_mdi * installation_check(int); +static f_find scan_drives; +static f_find walk_safe_hooks; +static const s_safe_hook * is_safe_hook(const void *); +static const s_mdi * is_memdisk_hook(const s_safe_hook *); +static f_find scan_mbfts; +static const s_mbft * is_mbft(const void *); +static f_find do_nothing; +static void memdisk_info(const s_mdi *); +static void boot_args(char **); +static const char * bootloadername(uint8_t); + +/*** Structure/union definitions */ + +/*** Objects */ +static int show_info = 0; + +/*** Function definitions */ + +int main(int argc, char ** argv) { + static f_find * do_scan_drives = scan_drives; + static f_find * do_walk_safe_hooks = do_nothing; + static f_find * do_scan_mbfts = do_nothing; + char ** detected_cmd; + char ** not_detected_cmd; + char ** cmd; + char ** cur_arg; + int show_usage; + int found; + + (void) argc; + + openconsole(&dev_null_r, &dev_stdcon_w); + + detected_cmd = NULL; + not_detected_cmd = NULL; + show_usage = 1; + for (cur_arg = argv + 1; *cur_arg; ++cur_arg) { + /* Check for command divider */ + if (!strcmp(*cur_arg, "--")) { + show_usage = 0; + *cur_arg = NULL; + not_detected_cmd = cur_arg + 1; + break; + } + + /* Check for '--info' */ + if (!strcmp(*cur_arg, "--info")) { + show_usage = 0; + show_info = 1; + continue; + } + + if (!strcmp(*cur_arg, "--no-sequential")) { + do_scan_drives = do_nothing; + continue; + } + + if (!strcmp(*cur_arg, "--safe-hooks")) { + do_walk_safe_hooks = walk_safe_hooks; + continue; + } + + if (!strcmp(*cur_arg, "--mbfts")) { + do_scan_mbfts = scan_mbfts; + continue; + } + + /* Check for invalid option */ + if (!memcmp(*cur_arg, "--", sizeof "--" - 1)) { + puts("Invalid option!"); + show_usage = 1; + break; + } + + /* Set 'detected_cmd' if it's null */ + if (!detected_cmd) + detected_cmd = cur_arg; + + continue; + } + + if (show_usage) { + fprintf(stderr, usage_text); + return 1; + } + + found = 0; + found += do_walk_safe_hooks(); + found += do_scan_mbfts(); + found += do_scan_drives(); + + cmd = found ? detected_cmd : not_detected_cmd; + if (cmd) + boot_args(cmd); + + return 0; + } + +static const s_mdi * installation_check(int drive) { + com32sys_t params, results; + int found; + + /* Set parameters for INT 0x13 call */ + memset(¶ms, 0, sizeof params); + params.eax.w[0] = M_GET_DRIVE_PARAMS << 8; + params.edx.w[0] = drive; + /* 'ME' 'MD' 'IS' 'K?' */ + params.eax.w[1] = 0x454D; + params.ecx.w[1] = 0x444D; + params.edx.w[1] = 0x5349; + params.ebx.w[1] = 0x3F4B; + + /* Perform the call */ + __intcall(0x13, ¶ms, &results); + + /* Check result */ + found = ( + /* '!M' 'EM' 'DI' 'SK' */ + results.eax.w[1] == 0x4D21 && + results.ecx.w[1] == 0x4D45 && + results.edx.w[1] == 0x4944 && + results.ebx.w[1] == 0x4B53 + ); + + if (found) + return MK_PTR(results.es, results.edi.w[0]); + + return NULL; + } + +static int scan_drives(void) { + int found, drive; + const s_mdi * mdi; + + for (found = drive = 0; drive <= 0xFF; ++drive) { + mdi = installation_check(drive); + if (!mdi) + continue; + + memdisk_info(mdi); + ++found; + continue; + } + + return found; + } + +static int walk_safe_hooks(void) { + static const u_segoff * const int13 = (void *) M_INT13H; + const void * addr; + int found; + const s_safe_hook * hook; + const s_mdi * mdi; + + /* INT 0x13 vector */ + addr = MK_PTR(int13->seg_off.segment, int13->seg_off.offset); + found = 0; + while ((hook = is_safe_hook(addr))) { + if ((mdi = is_memdisk_hook(hook))) { + memdisk_info(mdi); + ++found; + } + + addr = MK_PTR( + hook->old_hook.seg_off.segment, + hook->old_hook.seg_off.offset + ); + continue; + } + return found; + } + +static const s_safe_hook * is_safe_hook(const void * addr) { + static const char magic[] = "$INT13SF"; + const s_safe_hook * test; + + test = addr; + if (memcmp(test->signature, magic, sizeof magic - 1)) + return NULL; + + return addr; + } + +static const s_mdi * is_memdisk_hook(const s_safe_hook * hook) { + static const char magic[] = "MEMDISK"; + const s_mbft * mbft; + + if (memcmp(hook->vendor, magic, sizeof magic - 1)) + return NULL; + + /* An mBFT is always aligned */ + mbft = MK_PTR(hook->mbft >> 4, 0); + return &mbft->mdi; + } + +static int scan_mbfts(void) { + static const uint16_t * const free_base_mem = (void *) M_FREEBASEMEM; + static const void * const top = (void *) M_TOP; + const void * addr; + const s_mbft * mbft; + int found; + + addr = MK_PTR(*free_base_mem << 4, 0); + found = 0; + for (addr = MK_PTR(*free_base_mem << 4, 0); addr < top; addr += 1 << 4) { + if (!(mbft = is_mbft(addr))) + continue; + + memdisk_info(&mbft->mdi); + ++found; + continue; + } + + return found; + } + +static const s_mbft * is_mbft(const void * addr) { + static const char magic[] = "mBFT"; + const s_mbft * const test = addr; + + if (memcmp(test->acpi.signature, magic, sizeof magic - 1)) + return NULL; + + if (test->acpi.length != sizeof *test) + return NULL; + + { const uint8_t * const end = (void *) (test + 1); + const uint8_t * ptr; + uint8_t chksum; + + chksum = 0; + for (ptr = addr; ptr < end; ++ptr) + chksum += *ptr; + if (chksum) + return NULL; + } + + /* Looks like it's a mBFT! */ + return test; + } + +static int do_nothing(void) { + return 0; + } + +static void memdisk_info(const s_mdi * mdi) { + const char * cmdline; + + if (!show_info) + return; + + cmdline = MK_PTR( + mdi->cmdline.seg_off.segment, + mdi->cmdline.seg_off.offset + ); + printf( + "Found MEMDISK version %u.%02u:\n" + " diskbuf == 0x%08X, disksize == %u sectors\n" + " bootloaderid == 0x%02X (%s),\n" + " cmdline: %s\n", + mdi->version_major, + mdi->version_minor, + mdi->diskbuf, + mdi->disksize, + mdi->bootloaderid, + bootloadername(mdi->bootloaderid), + cmdline + ); + return; + } + +/* This function copyright H. Peter Anvin */ +static void boot_args(char **args) +{ + int len = 0, a = 0; + char **pp; + const char *p; + char c, *q, *str; + + for (pp = args; *pp; pp++) + len += strlen(*pp) + 1; + + q = str = alloca(len); + for (pp = args; *pp; pp++) { + p = *pp; + while ((c = *p++)) + *q++ = c; + *q++ = ' '; + a = 1; + } + q -= a; + *q = '\0'; + + if (!str[0]) + syslinux_run_default(); + else + syslinux_run_command(str); +} + +/* This function copyright H. Peter Anvin */ +static const char *bootloadername(uint8_t id) +{ + static const struct { + uint8_t id, mask; + const char *name; + } *lp, list[] = { + {0x00, 0xf0, "LILO"}, + {0x10, 0xf0, "LOADLIN"}, + {0x31, 0xff, "SYSLINUX"}, + {0x32, 0xff, "PXELINUX"}, + {0x33, 0xff, "ISOLINUX"}, + {0x34, 0xff, "EXTLINUX"}, + {0x30, 0xf0, "Syslinux family"}, + {0x40, 0xf0, "Etherboot"}, + {0x50, 0xf0, "ELILO"}, + {0x70, 0xf0, "GrUB"}, + {0x80, 0xf0, "U-Boot"}, + {0xA0, 0xf0, "Gujin"}, + {0xB0, 0xf0, "Qemu"}, + {0x00, 0x00, "unknown"} + }; + + for (lp = list;; lp++) { + if (((id ^ lp->id) & lp->mask) == 0) + return lp->name; + } +} + -- 1.6.0.4 -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: 0001-ifmemdsk.c32-Allow-boot-options-based-on-presence-o.patch URL: <http://www.zytor.com/pipermail/syslinux/attachments/20110806/6cc11219/attachment.ksh>
Bernd Blaauw
2011-Aug-06 10:29 UTC
[syslinux] [PATCH] ifmemdsk.c32: Allow boot options based on presence of MEMDISK
Op 6-8-2011 11:43, Shao Miller schreef:> Below, attached, and available at the 'ifmemdsk' branch at: > > http://git.zytor.com/?p=users/sha0/syslinux.git;a=commitdiff;h=a975c12919bbd48739fede4ebfe099d98b87192e > > > Review welcome!Interesting. I'll await one of HPA's 4.10 test releases for this unless someone got a binary (.c32) handy somewhere. My use case for an inner MEMDISK-loaded ISO would be to either suppress the menu or to start a default entry. Slightly offtopic: * is CHAIN.C32 working for FreeLDR (trunk) ? Mboot.c32 only partial, due to 'root' requirement. * is an IsoHybrid image possible with only DOS in it? I can imagine the script adding MBR, maybe partition layout, but not bootsector. It would also mean adding a kernel and config file at root of ISO. Think I opened some Isyhybrid file a while ago, WinImage wasn't happy with it at all.
Bernd Blaauw
2011-Aug-07 23:01 UTC
[syslinux] [PATCH] ifmemdsk.c32: Allow boot options based on presence of MEMDISK
Op 6-8-2011 11:43, Shao Miller schreef:> Below, attached, and available at the 'ifmemdsk' branch at: > > http://git.zytor.com/?p=users/sha0/syslinux.git;a=commitdiff;h=a975c12919bbd48739fede4ebfe099d98b87192e > > > Review welcome!I've received a binary and did some short initial tests. It appears the detection is based on memdisk itself , rather than which bootloader loaded it or which appended arguments were given. Good enough for me :) Based on my needs (boot diskette image if Memdisk already loaded, otherwise show menu) I'll likely need 2 different config files, as shown below in some semi-syntax. Single config file impossible? (Not showing a menu when MEMDISK detected works fine for ISOLINUX, for PXE-Linux it's probably an entirely different story as no menu was shown before.) syslinux.cfg: com32 ifmemdsk.c32 --mbfts [label 1] -- [label2] label 1 kernel memdisk bootdisk.img label 2 config bigmenu.cfg and bigmenu.cfg being my current MENU.C32-using syslinux.cfg Is there a way to specify alternate options if file doesn't exist or doesn't fit in memory? I guess options 3 and 4 are fallback for both the 'memdisk detected' and the 'no memdisk found' scenario. com32 ifmemdsk.c32 --mbfts label 1 -- label 2 -- label 3 --label 4 label 1 # small bootdisk image, will load always kernel memdisk bootdisk.img label 2 # Memdisk not found, so MEMDISK-load ISO(provided it exists and fits) kernel memdisk iso bootcd.iso label 3 # hm the ISO didn't exist, fallback..to same as 1 # provided memdisk doesn't hang kernel memdisk bootdisk.img label 4 # hm the ISO didn't fit in memory, fallback..to same as 1 # provided memdisk doesn't hang kernel memdisk bootdisk.img
Miller, Shao
2011-Aug-08 13:32 UTC
[syslinux] [PATCH] ifmemdsk.c32: Allow boot options based on presence of MEMDISK
Some minor touch-ups and an attempt to avoid scrambling the below patch in this very e-mail. Below, attached, and available at the 'ifmemdsk' branch at: http://git.zytor.com/?p=users/sha0/syslinux.git;a=shortlog;h=refs/heads/ ifmemdsk Review welcome! - Shao Miller ----- From e3f4df5bf10f5a64cfffdaa4f40a3960bd98cb95 Mon Sep 17 00:00:00 2001 From: Shao Miller <shao.miller at yrdsb.edu.on.ca> Date: Sat, 6 Aug 2011 05:24:46 -0400 Subject: [PATCH] ifmemdsk.c32: Allow boot options based on presence of MEMDISK Like 'ifcpu.c32' and 'ifplop.c32', this COMBOOT32 module will check for the presence of MEMDISK(s) and choose one of two (optionally) specified commands. Signed-off-by: Shao Miller <shao.miller at yrdsb.edu.on.ca> --- NEWS | 1 + com32/modules/ifmemdsk.c | 392 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 393 insertions(+), 0 deletions(-) create mode 100755 com32/modules/ifmemdsk.c diff --git a/NEWS b/NEWS index 88adba1..7700504 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ Changes in 4.05: on virtually all systems since the beginning, and has been totally broken since 4.00 at least. Use MEMDISK instead. * chain.c32: Support chaining ReactOS' FreeLdr (Shao Miller) + * ifmemdsk.c32: Choose boot option based on presence of MEMDISK Changes in 4.04: * PXELINUX: Fix handling of unqualified DNS names. diff --git a/com32/modules/ifmemdsk.c b/com32/modules/ifmemdsk.c new file mode 100755 index 0000000..cfed87f --- /dev/null +++ b/com32/modules/ifmemdsk.c @@ -0,0 +1,392 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2011 Shao Miller - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/**** + * @file ifmemdsk.c + * + * This COM32 module detects if there are MEMDISKs established. + */ + +static const char usage_text[] = "\ +Usage:\n\ + ifmemdsk.c32 [<option> [...]] --info [<option> [...]]\n\ + ifmemdsk.c32 [<option> [...]] [<detected_cmd>] -- [<not_detected_cmd>]\n\ +\n\ +Options:\n\ + --info . . . . . Displays info about MEMDISK(s)\n\ + --safe-hooks . . Will scan INT 13h \"safe hook\" chain\n\ + --mbfts . . . . . Will scan memory for MEMDISK mBFTs\n\ + --no-sequential Suppresses probing all drive numbers\n\ +\n\ +If a MEMDISK is found, or if a particular MEMDISK is sought by the options\n\ +and is found, then the 'detected_cmd' action will be taken, else the\n\ +'not_detected_cmd' action will be taken.\n\ +\n"; + +#include <stdio.h> +#include <string.h> +#include <alloca.h> +#include <com32.h> +#include <console.h> +#include <syslinux/boot.h> + +/* Pull in MEMDISK common structures */ +#include "../../memdisk/mstructs.h" + +/*** Macros */ +#define M_GET_DRIVE_PARAMS (0x08) +#define M_SEGOFFTOPTR(seg, off) (((seg) << 4) + (off)) +#define M_INT13H M_SEGOFFTOPTR(0x0000, 0x0013 * 4) +#define M_FREEBASEMEM M_SEGOFFTOPTR(0x0040, 0x0013) +#define M_TOP M_SEGOFFTOPTR(0x9FFF, 0x0000) + +/*** Object types */ +typedef struct mdi s_mdi; +typedef real_addr_t u_segoff; +typedef struct safe_hook s_safe_hook; +typedef struct mBFT s_mbft; + +/*** Function types */ +typedef int f_find(void); + +/*** Function declarations */ +static const s_mdi * installation_check(int); +static f_find scan_drives; +static f_find walk_safe_hooks; +static const s_safe_hook * is_safe_hook(const void *); +static const s_mdi * is_memdisk_hook(const s_safe_hook *); +static f_find scan_mbfts; +static const s_mbft * is_mbft(const void *); +static f_find do_nothing; +static void memdisk_info(const s_mdi *); +static void boot_args(char **); +static const char * bootloadername(uint8_t); + +/*** Structure/union definitions */ + +/*** Objects */ +static int show_info = 0; + +/*** Function definitions */ + +int main(int argc, char ** argv) { + static f_find * do_scan_drives = scan_drives; + static f_find * do_walk_safe_hooks = do_nothing; + static f_find * do_scan_mbfts = do_nothing; + char ** detected_cmd; + char ** not_detected_cmd; + char ** cmd; + char ** cur_arg; + int show_usage; + int found; + + (void) argc; + + openconsole(&dev_null_r, &dev_stdcon_w); + + detected_cmd = NULL; + not_detected_cmd = NULL; + show_usage = 1; + for (cur_arg = argv + 1; *cur_arg; ++cur_arg) { + /* Check for command divider */ + if (!strcmp(*cur_arg, "--")) { + show_usage = 0; + *cur_arg = NULL; + not_detected_cmd = cur_arg + 1; + break; + } + + /* Check for '--info' */ + if (!strcmp(*cur_arg, "--info")) { + show_usage = 0; + show_info = 1; + continue; + } + + /* Other options */ + if (!strcmp(*cur_arg, "--no-sequential")) { + do_scan_drives = do_nothing; + continue; + } + + if (!strcmp(*cur_arg, "--safe-hooks")) { + do_walk_safe_hooks = walk_safe_hooks; + continue; + } + + if (!strcmp(*cur_arg, "--mbfts")) { + do_scan_mbfts = scan_mbfts; + continue; + } + + /* Check for invalid option */ + if (!memcmp(*cur_arg, "--", sizeof "--" - 1)) { + puts("Invalid option!"); + show_usage = 1; + break; + } + + /* Set 'detected_cmd' if it's null */ + if (!detected_cmd) + detected_cmd = cur_arg; + + continue; + } + + if (show_usage) { + fprintf(stderr, usage_text); + return 1; + } + + found = 0; + found += do_walk_safe_hooks(); + found += do_scan_mbfts(); + found += do_scan_drives(); + + cmd = found ? detected_cmd : not_detected_cmd; + if (cmd && *cmd) + boot_args(cmd); + + return 0; + } + +static const s_mdi * installation_check(int drive) { + com32sys_t params, results; + int found; + + /* Set parameters for INT 0x13 call */ + memset(¶ms, 0, sizeof params); + params.eax.w[0] = M_GET_DRIVE_PARAMS << 8; + params.edx.w[0] = drive; + /* 'ME' 'MD' 'IS' 'K?' */ + params.eax.w[1] = 0x454D; + params.ecx.w[1] = 0x444D; + params.edx.w[1] = 0x5349; + params.ebx.w[1] = 0x3F4B; + + /* Perform the call */ + __intcall(0x13, ¶ms, &results); + + /* Check result */ + found = ( + /* '!M' 'EM' 'DI' 'SK' */ + results.eax.w[1] == 0x4D21 && + results.ecx.w[1] == 0x4D45 && + results.edx.w[1] == 0x4944 && + results.ebx.w[1] == 0x4B53 + ); + + if (found) + return MK_PTR(results.es, results.edi.w[0]); + + return NULL; + } + +static int scan_drives(void) { + int found, drive; + const s_mdi * mdi; + + for (found = drive = 0; drive <= 0xFF; ++drive) { + mdi = installation_check(drive); + if (!mdi) + continue; + + memdisk_info(mdi); + ++found; + continue; + } + + return found; + } + +static int walk_safe_hooks(void) { + static const u_segoff * const int13 = (void *) M_INT13H; + const void * addr; + int found; + const s_safe_hook * hook; + const s_mdi * mdi; + + /* INT 0x13 vector */ + addr = MK_PTR(int13->seg_off.segment, int13->seg_off.offset); + found = 0; + while (addr) { + hook = is_safe_hook(addr); + if (!hook) + break; + + mdi = is_memdisk_hook(hook); + if (mdi) { + memdisk_info(mdi); + ++found; + } + + addr = MK_PTR( + hook->old_hook.seg_off.segment, + hook->old_hook.seg_off.offset + ); + continue; + } + return found; + } + +static const s_safe_hook * is_safe_hook(const void * addr) { + static const char magic[] = "$INT13SF"; + const s_safe_hook * const test = addr; + + if (memcmp(test->signature, magic, sizeof magic - 1)) + return NULL; + + return test; + } + +static const s_mdi * is_memdisk_hook(const s_safe_hook * hook) { + static const char magic[] = "MEMDISK"; + const s_mbft * mbft; + + if (memcmp(hook->vendor, magic, sizeof magic - 1)) + return NULL; + + /* An mBFT is always aligned */ + mbft = MK_PTR(hook->mbft >> 4, 0); + return &mbft->mdi; + } + +static int scan_mbfts(void) { + static const uint16_t * const free_base_mem = (void *) M_FREEBASEMEM; + static const void * const top = (void *) M_TOP; + const void * addr; + const s_mbft * mbft; + int found; + + found = 0; + for (addr = MK_PTR(*free_base_mem << 4, 0); addr < top; addr += 1 << 4) { + if (!(mbft = is_mbft(addr))) + continue; + + memdisk_info(&mbft->mdi); + ++found; + continue; + } + + return found; + } + +static const s_mbft * is_mbft(const void * addr) { + static const char magic[] = "mBFT"; + const s_mbft * const test = addr; + const uint8_t * ptr, * end; + uint8_t chksum; + + if (memcmp(test->acpi.signature, magic, sizeof magic - 1)) + return NULL; + + if (test->acpi.length != sizeof *test) + return NULL; + + end = (void *) (test + 1); + chksum = 0; + for (ptr = addr; ptr < end; ++ptr) + chksum += *ptr; + if (chksum) + return NULL; + + /* Looks like it's an mBFT! */ + return test; + } + +static int do_nothing(void) { + return 0; + } + +static void memdisk_info(const s_mdi * mdi) { + const char * cmdline; + + if (!show_info) + return; + + cmdline = MK_PTR( + mdi->cmdline.seg_off.segment, + mdi->cmdline.seg_off.offset + ); + printf( + "Found MEMDISK version %u.%02u:\n" + " diskbuf == 0x%08X, disksize == %u sectors\n" + " bootloaderid == 0x%02X (%s),\n" + " cmdline: %s\n", + mdi->version_major, + mdi->version_minor, + mdi->diskbuf, + mdi->disksize, + mdi->bootloaderid, + bootloadername(mdi->bootloaderid), + cmdline + ); + return; + } + +/* This function copyright H. Peter Anvin */ +static void boot_args(char **args) +{ + int len = 0, a = 0; + char **pp; + const char *p; + char c, *q, *str; + + for (pp = args; *pp; pp++) + len += strlen(*pp) + 1; + + q = str = alloca(len); + for (pp = args; *pp; pp++) { + p = *pp; + while ((c = *p++)) + *q++ = c; + *q++ = ' '; + a = 1; + } + q -= a; + *q = '\0'; + + if (!str[0]) + syslinux_run_default(); + else + syslinux_run_command(str); +} + +/* This function copyright H. Peter Anvin */ +static const char *bootloadername(uint8_t id) +{ + static const struct { + uint8_t id, mask; + const char *name; + } *lp, list[] = { + {0x00, 0xf0, "LILO"}, + {0x10, 0xf0, "LOADLIN"}, + {0x31, 0xff, "SYSLINUX"}, + {0x32, 0xff, "PXELINUX"}, + {0x33, 0xff, "ISOLINUX"}, + {0x34, 0xff, "EXTLINUX"}, + {0x30, 0xf0, "Syslinux family"}, + {0x40, 0xf0, "Etherboot"}, + {0x50, 0xf0, "ELILO"}, + {0x70, 0xf0, "GrUB"}, + {0x80, 0xf0, "U-Boot"}, + {0xA0, 0xf0, "Gujin"}, + {0xB0, 0xf0, "Qemu"}, + {0x00, 0x00, "unknown"} + }; + + for (lp = list;; lp++) { + if (((id ^ lp->id) & lp->mask) == 0) + return lp->name; + } +} + -- 1.6.0.4 -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-ifmemdsk.c32-Allow-boot-options-based-on-presence-o.patch Type: application/octet-stream Size: 11263 bytes Desc: 0001-ifmemdsk.c32-Allow-boot-options-based-on-presence-o.patch URL: <http://www.zytor.com/pipermail/syslinux/attachments/20110808/73d89e14/attachment.obj>
Bernd Blaauw
2011-Aug-10 20:04 UTC
[syslinux] [PATCH] ifmemdsk.c32: Allow boot options based on presence of MEMDISK
Op 6-8-2011 11:43, Shao Miller schreef:> Below, attached, and available at the 'ifmemdsk' branch at: > > http://git.zytor.com/?p=users/sha0/syslinux.git;a=commitdiff;h=a975c12919bbd48739fede4ebfe099d98b87192e > > > Review welcome!I'll implement your ifmemdsk module anyway, but just realised I'm kinda being silly for building a small shell around my (inner) ISO. A better question therefor is: "is it possible to use some memdisk-like module to mirror the boot medium itself to RAM then boot from it?". a MEMDISK-SELF module, sort of. For anything over 100MB or so this might not be fun though, likely consuming too much time. But it could work for small 'CDs' and 'diskettes' (or anything resembling it). floppy --> bootsector --> syslinux --> ifmemdsk.c32 --> memdisk-self --> (ram-img) --> bs --> syslinux --> ifmemdsk --> "chain.c32 something.bss" Seeing as the ELTORITO driver finds some kind of ISO9660 bootsector / magic hook, same procedure might work for Isolinux (read/copy blocks till done) I admit all this stuff is way too realmode/DOS-specific, might thus not be worth general coding time as there's a current option that works (ISO + tiny shell and for low end systems a tiny bootdisk image)