source: bootcd/isolinux/syslinux-6.03/com32/modules/ifmemdsk.c @ e16e8f2

Last change on this file since e16e8f2 was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 9.4 KB
Line 
1/* ----------------------------------------------------------------------- *
2 *
3 *   Copyright 2011 Shao Miller - All Rights Reserved
4 *
5 *   This program is free software; you can redistribute it and/or modify
6 *   it under the terms of the GNU General Public License as published by
7 *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
8 *   Boston MA 02110-1301, USA; either version 2 of the License, or
9 *   (at your option) any later version; incorporated herein by reference.
10 *
11 * ----------------------------------------------------------------------- */
12
13/****
14 * @file ifmemdsk.c
15 *
16 * This COM32 module detects if there are MEMDISKs established.
17 */
18
19static const char usage_text[] = "\
20Usage:\n\
21  ifmemdsk.c32 [<option> [...]] --info [<option> [...]]\n\
22  ifmemdsk.c32 [<option> [...]] [<detected_cmd>] -- [<not_detected_cmd>]\n\
23\n\
24Options:\n\
25  --info  . . . . . Displays info about MEMDISK(s)\n\
26  --safe-hooks . .  Will scan INT 13h \"safe hook\" chain\n\
27  --mbfts . . . . . Will scan memory for MEMDISK mBFTs\n\
28  --no-sequential   Suppresses probing all drive numbers\n\
29\n\
30If a MEMDISK is found, or if a particular MEMDISK is sought by the options\n\
31and is found, then the 'detected_cmd' action will be taken, else the\n\
32'not_detected_cmd' action will be taken.\n\
33\n";
34
35#include <stdio.h>
36#include <string.h>
37#include <alloca.h>
38#include <com32.h>
39#include <console.h>
40#include <syslinux/boot.h>
41
42/* Pull in MEMDISK common structures */
43#include "../../memdisk/mstructs.h"
44
45/*** Macros */
46#define M_GET_DRIVE_PARAMS (0x08)
47#define M_SEGOFFTOPTR(seg, off) (((seg) << 4) + (off))
48#define M_INT13H M_SEGOFFTOPTR(0x0000, 0x0013 * 4)
49#define M_FREEBASEMEM M_SEGOFFTOPTR(0x0040, 0x0013)
50#define M_TOP M_SEGOFFTOPTR(0x9FFF, 0x0000)
51
52/*** Object types */
53typedef struct mdi s_mdi;
54typedef real_addr_t u_segoff;
55typedef struct safe_hook s_safe_hook;
56typedef struct mBFT s_mbft;
57
58/*** Function types */
59typedef int f_find(void);
60
61/*** Function declarations */
62static const s_mdi * installation_check(int);
63static f_find scan_drives;
64static f_find walk_safe_hooks;
65static const s_safe_hook * is_safe_hook(const void *);
66static const s_mdi * is_memdisk_hook(const s_safe_hook *);
67static f_find scan_mbfts;
68static const s_mbft * is_mbft(const void *);
69static f_find do_nothing;
70static void memdisk_info(const s_mdi *);
71static void boot_args(char **);
72static const char * bootloadername(uint8_t);
73
74/*** Structure/union definitions */
75
76/*** Objects */
77static int show_info = 0;
78
79/*** Function definitions */
80
81int main(int argc, char ** argv) {
82    static f_find * do_scan_drives = scan_drives;
83    static f_find * do_walk_safe_hooks = do_nothing;
84    static f_find * do_scan_mbfts = do_nothing;
85    char ** detected_cmd;
86    char ** not_detected_cmd;
87    char ** cmd;
88    char ** cur_arg;
89    int show_usage;
90    int found;
91
92    (void) argc;
93
94    openconsole(&dev_null_r, &dev_stdcon_w);
95
96    detected_cmd = NULL;
97    not_detected_cmd = NULL;
98    show_usage = 1;
99    for (cur_arg = argv + 1; *cur_arg; ++cur_arg) {
100        /* Check for command divider */
101        if (!strcmp(*cur_arg, "--")) {
102            show_usage = 0;
103            *cur_arg = NULL;
104            not_detected_cmd = cur_arg + 1;
105            break;
106          }
107
108        /* Check for '--info' */
109        if (!strcmp(*cur_arg, "--info")) {
110            show_usage = 0;
111            show_info = 1;
112            continue;
113          }
114
115        /* Other options */
116        if (!strcmp(*cur_arg, "--no-sequential")) {
117            do_scan_drives = do_nothing;
118            continue;
119          }
120
121        if (!strcmp(*cur_arg, "--safe-hooks")) {
122            do_walk_safe_hooks = walk_safe_hooks;
123            continue;
124          }
125
126        if (!strcmp(*cur_arg, "--mbfts")) {
127            do_scan_mbfts = scan_mbfts;
128            continue;
129          }
130
131        /* Check for invalid option */
132        if (!memcmp(*cur_arg, "--", sizeof "--" - 1)) {
133            puts("Invalid option!");
134            show_usage = 1;
135            break;
136          }
137
138        /* Set 'detected_cmd' if it's null */
139        if (!detected_cmd)
140          detected_cmd = cur_arg;
141
142        continue;
143      }
144
145    if (show_usage) {
146        fprintf(stderr, usage_text);
147        return 1;
148      }
149
150    found = 0;
151    found += do_walk_safe_hooks();
152    found += do_scan_mbfts();
153    found += do_scan_drives();
154
155    cmd = found ? detected_cmd : not_detected_cmd;
156    if (cmd && *cmd)
157      boot_args(cmd);
158
159    return 0;
160  }
161
162static const s_mdi * installation_check(int drive) {
163    com32sys_t params, results;
164    int found;
165
166    /* Set parameters for INT 0x13 call */
167    memset(&params, 0, sizeof params);
168    params.eax.w[0] = M_GET_DRIVE_PARAMS << 8;
169    params.edx.w[0] = drive;
170    /* 'ME' 'MD' 'IS' 'K?' */
171    params.eax.w[1] = 0x454D;
172    params.ecx.w[1] = 0x444D;
173    params.edx.w[1] = 0x5349;
174    params.ebx.w[1] = 0x3F4B;
175
176    /* Perform the call */
177    __intcall(0x13, &params, &results);
178
179    /* Check result */
180    found = (
181        /* '!M' 'EM' 'DI' 'SK' */
182        results.eax.w[1] == 0x4D21 &&
183        results.ecx.w[1] == 0x4D45 &&
184        results.edx.w[1] == 0x4944 &&
185        results.ebx.w[1] == 0x4B53
186      );
187
188    if (found)
189      return MK_PTR(results.es, results.edi.w[0]);
190
191    return NULL;
192  }
193
194static int scan_drives(void) {
195    int found, drive;
196    const s_mdi * mdi;
197
198    for (found = drive = 0; drive <= 0xFF; ++drive) {
199        mdi = installation_check(drive);
200        if (!mdi)
201          continue;
202
203        memdisk_info(mdi);
204        ++found;
205        continue;
206      }
207
208    return found;
209  }
210
211static int walk_safe_hooks(void) {
212    static const u_segoff * const int13 = (void *) M_INT13H;
213    const void * addr;
214    int found;
215    const s_safe_hook * hook;
216    const s_mdi * mdi;
217
218    /* INT 0x13 vector */
219    addr = MK_PTR(int13->seg_off.segment, int13->seg_off.offset);
220    found = 0;
221    while (addr) {
222        hook = is_safe_hook(addr);
223        if (!hook)
224          break;
225
226        mdi = is_memdisk_hook(hook);
227        if (mdi) {
228            memdisk_info(mdi);
229            ++found;
230          }
231
232        addr = MK_PTR(
233            hook->old_hook.seg_off.segment,
234            hook->old_hook.seg_off.offset
235          );
236        continue;
237      }
238    return found;
239  }
240
241static const s_safe_hook * is_safe_hook(const void * addr) {
242    static const char magic[] = "$INT13SF";
243    const s_safe_hook * const test = addr;
244
245    if (memcmp(test->signature, magic, sizeof magic - 1))
246      return NULL;
247
248    return test;
249  }
250
251static const s_mdi * is_memdisk_hook(const s_safe_hook * hook) {
252    static const char magic[] = "MEMDISK";
253    const s_mbft * mbft;
254
255    if (memcmp(hook->vendor, magic, sizeof magic - 1))
256      return NULL;
257
258    /* An mBFT is always aligned */
259    mbft = MK_PTR(hook->mbft >> 4, 0);
260    return &mbft->mdi;
261  }
262
263static int scan_mbfts(void) {
264    static const uint16_t * const free_base_mem = (void *) M_FREEBASEMEM;
265    static const void * const top = (void *) M_TOP;
266    const void * addr;
267    const s_mbft * mbft;
268    int found;
269
270    found = 0;
271    for (addr = MK_PTR(*free_base_mem << 4, 0); addr < top; addr += 1 << 4) {
272        if (!(mbft = is_mbft(addr)))
273          continue;
274
275        memdisk_info(&mbft->mdi);
276        ++found;
277        continue;
278      }
279
280    return found;
281  }
282
283static const s_mbft * is_mbft(const void * addr) {
284    static const char magic[] = "mBFT";
285    const s_mbft * const test = addr;
286    const uint8_t * ptr, * end;
287    uint8_t chksum;
288
289    if (memcmp(test->acpi.signature, magic, sizeof magic - 1))
290      return NULL;
291
292    if (test->acpi.length != sizeof *test)
293      return NULL;
294
295    end = (void *) (test + 1);
296    chksum = 0;
297    for (ptr = addr; ptr < end; ++ptr)
298      chksum += *ptr;
299    if (chksum)
300      return NULL;
301
302    /* Looks like it's an mBFT! */
303    return test;
304  }
305
306static int do_nothing(void) {
307    return 0;
308  }
309
310static void memdisk_info(const s_mdi * mdi) {
311    const char * cmdline;
312
313    if (!show_info)
314      return;
315
316    cmdline = MK_PTR(
317        mdi->cmdline.seg_off.segment,
318        mdi->cmdline.seg_off.offset
319      );
320    printf(
321        "Found MEMDISK version %u.%02u:\n"
322        "  diskbuf == 0x%08X, disksize == %u sectors\n"
323        "  bootloaderid == 0x%02X (%s),\n"
324        "  cmdline: %s\n",
325        mdi->version_major,
326        mdi->version_minor,
327        mdi->diskbuf,
328        mdi->disksize,
329        mdi->bootloaderid,
330        bootloadername(mdi->bootloaderid),
331        cmdline
332      );
333    return;
334  }
335
336/* This function copyright H. Peter Anvin */
337static void boot_args(char **args)
338{
339    int len = 0, a = 0;
340    char **pp;
341    const char *p;
342    char c, *q, *str;
343
344    for (pp = args; *pp; pp++)
345        len += strlen(*pp) + 1;
346
347    q = str = alloca(len);
348    for (pp = args; *pp; pp++) {
349        p = *pp;
350        while ((c = *p++))
351            *q++ = c;
352        *q++ = ' ';
353        a = 1;
354    }
355    q -= a;
356    *q = '\0';
357
358    if (!str[0])
359        syslinux_run_default();
360    else
361        syslinux_run_command(str);
362}
363
364/* This function copyright H. Peter Anvin */
365static const char *bootloadername(uint8_t id)
366{
367    static const struct {
368        uint8_t id, mask;
369        const char *name;
370    } *lp, list[] = {
371        {0x00, 0xf0, "LILO"},
372        {0x10, 0xf0, "LOADLIN"},
373        {0x31, 0xff, "SYSLINUX"},
374        {0x32, 0xff, "PXELINUX"},
375        {0x33, 0xff, "ISOLINUX"},
376        {0x34, 0xff, "EXTLINUX"},
377        {0x30, 0xf0, "Syslinux family"},
378        {0x40, 0xf0, "Etherboot"},
379        {0x50, 0xf0, "ELILO"},
380        {0x70, 0xf0, "GrUB"},
381        {0x80, 0xf0, "U-Boot"},
382        {0xA0, 0xf0, "Gujin"},
383        {0xB0, 0xf0, "Qemu"},
384        {0x00, 0x00, "unknown"}
385    };
386
387    for (lp = list;; lp++) {
388        if (((id ^ lp->id) & lp->mask) == 0)
389            return lp->name;
390    }
391}
392
Note: See TracBrowser for help on using the repository browser.