1 /* ----------------------------------------------------------------------- *
3 * Copyright 2011 Shao Miller - All Rights Reserved
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.
11 * ----------------------------------------------------------------------- */
16 * This COM32 module detects if there are MEMDISKs established.
19 static const char usage_text
[] = "\
21 ifmemdsk.c32 [<option> [...]] --info [<option> [...]]\n\
22 ifmemdsk.c32 [<option> [...]] [<detected_cmd>] -- [<not_detected_cmd>]\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\
30 If a MEMDISK is found, or if a particular MEMDISK is sought by the options\n\
31 and is found, then the 'detected_cmd' action will be taken, else the\n\
32 'not_detected_cmd' action will be taken.\n\
40 #include <syslinux/boot.h>
42 /* Pull in MEMDISK common structures */
43 #include "../../memdisk/mstructs.h"
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)
53 typedef struct mdi s_mdi
;
54 typedef real_addr_t u_segoff
;
55 typedef struct safe_hook s_safe_hook
;
56 typedef struct mBFT s_mbft
;
58 /*** Function types */
59 typedef int f_find(void);
61 /*** Function declarations */
62 static const s_mdi
* installation_check(int);
63 static f_find scan_drives
;
64 static f_find walk_safe_hooks
;
65 static const s_safe_hook
* is_safe_hook(const void *);
66 static const s_mdi
* is_memdisk_hook(const s_safe_hook
*);
67 static f_find scan_mbfts
;
68 static const s_mbft
* is_mbft(const void *);
69 static f_find do_nothing
;
70 static void memdisk_info(const s_mdi
*);
71 static void boot_args(char **);
72 static const char * bootloadername(uint8_t);
74 /*** Structure/union definitions */
77 static int show_info
= 0;
79 /*** Function definitions */
81 int 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
;
86 char ** not_detected_cmd
;
94 openconsole(&dev_null_r
, &dev_stdcon_w
);
97 not_detected_cmd
= NULL
;
99 for (cur_arg
= argv
+ 1; *cur_arg
; ++cur_arg
) {
100 /* Check for command divider */
101 if (!strcmp(*cur_arg
, "--")) {
104 not_detected_cmd
= cur_arg
+ 1;
108 /* Check for '--info' */
109 if (!strcmp(*cur_arg
, "--info")) {
116 if (!strcmp(*cur_arg
, "--no-sequential")) {
117 do_scan_drives
= do_nothing
;
121 if (!strcmp(*cur_arg
, "--safe-hooks")) {
122 do_walk_safe_hooks
= walk_safe_hooks
;
126 if (!strcmp(*cur_arg
, "--mbfts")) {
127 do_scan_mbfts
= scan_mbfts
;
131 /* Check for invalid option */
132 if (!memcmp(*cur_arg
, "--", sizeof "--" - 1)) {
133 puts("Invalid option!");
138 /* Set 'detected_cmd' if it's null */
140 detected_cmd
= cur_arg
;
146 fprintf(stderr
, usage_text
);
151 found
+= do_walk_safe_hooks();
152 found
+= do_scan_mbfts();
153 found
+= do_scan_drives();
155 cmd
= found
? detected_cmd
: not_detected_cmd
;
162 static const s_mdi
* installation_check(int drive
) {
163 com32sys_t params
, results
;
166 /* Set parameters for INT 0x13 call */
167 memset(¶ms
, 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;
176 /* Perform the call */
177 __intcall(0x13, ¶ms
, &results
);
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
189 return MK_PTR(results
.es
, results
.edi
.w
[0]);
194 static int scan_drives(void) {
198 for (found
= drive
= 0; drive
<= 0xFF; ++drive
) {
199 mdi
= installation_check(drive
);
211 static int walk_safe_hooks(void) {
212 static const u_segoff
* const int13
= (void *) M_INT13H
;
215 const s_safe_hook
* hook
;
218 /* INT 0x13 vector */
219 addr
= MK_PTR(int13
->seg_off
.segment
, int13
->seg_off
.offset
);
222 hook
= is_safe_hook(addr
);
226 mdi
= is_memdisk_hook(hook
);
233 hook
->old_hook
.seg_off
.segment
,
234 hook
->old_hook
.seg_off
.offset
241 static const s_safe_hook
* is_safe_hook(const void * addr
) {
242 static const char magic
[] = "$INT13SF";
243 const s_safe_hook
* const test
= addr
;
245 if (memcmp(test
->signature
, magic
, sizeof magic
- 1))
251 static const s_mdi
* is_memdisk_hook(const s_safe_hook
* hook
) {
252 static const char magic
[] = "MEMDISK";
255 if (memcmp(hook
->vendor
, magic
, sizeof magic
- 1))
258 /* An mBFT is always aligned */
259 mbft
= MK_PTR(hook
->mbft
>> 4, 0);
263 static 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
;
271 for (addr
= MK_PTR(*free_base_mem
<< 4, 0); addr
< top
; addr
+= 1 << 4) {
272 if (!(mbft
= is_mbft(addr
)))
275 memdisk_info(&mbft
->mdi
);
283 static 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
;
289 if (memcmp(test
->acpi
.signature
, magic
, sizeof magic
- 1))
292 if (test
->acpi
.length
!= sizeof *test
)
295 end
= (void *) (test
+ 1);
297 for (ptr
= addr
; ptr
< end
; ++ptr
)
302 /* Looks like it's an mBFT! */
306 static int do_nothing(void) {
310 static void memdisk_info(const s_mdi
* mdi
) {
311 const char * cmdline
;
317 mdi
->cmdline
.seg_off
.segment
,
318 mdi
->cmdline
.seg_off
.offset
321 "Found MEMDISK version %u.%02u:\n"
322 " diskbuf == 0x%08X, disksize == %u sectors\n"
323 " bootloaderid == 0x%02X (%s),\n"
330 bootloadername(mdi
->bootloaderid
),
336 /* This function copyright H. Peter Anvin */
337 static void boot_args(char **args
)
344 for (pp
= args
; *pp
; pp
++)
345 len
+= strlen(*pp
) + 1;
347 q
= str
= alloca(len
);
348 for (pp
= args
; *pp
; pp
++) {
359 syslinux_run_default();
361 syslinux_run_command(str
);
364 /* This function copyright H. Peter Anvin */
365 static const char *bootloadername(uint8_t id
)
367 static const struct {
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"}
387 for (lp
= list
;; lp
++) {
388 if (((id
^ lp
->id
) & lp
->mask
) == 0)