Hello Mike Banon,
I'd like you to do a code review. Please visit
https://review.coreboot.org/c/coreboot/+/32351
to review the following change.
Change subject: SeaBIOS - unofficial patches: advanced_bootmenu and multiple_floppies ......................................................................
SeaBIOS - unofficial patches: advanced_bootmenu and multiple_floppies
If you'd like to add the useful floppies to your coreboot (read about them at http://dangerousprototypes.com/docs/Lenovo_G505S_hacking#Useful_floppies ), or to use your USB numpad for choosing a SeaBIOS boot entry, then this change is for you! It contains two valuable patches together with a Makefile mod needed to automatically apply these patches to a cloned SeaBIOS before its' compilation.
advanced_bootmenu: up to 35 entries (2 pages if >18), numpad support (console) https://mail.coreboot.org/hyperkitty/list/seabios@seabios.org/thread/CKWLNTZ...
[PATCH v2] ramdisk: search for all available floppy images instead of one https://mail.coreboot.org/pipermail/seabios/2018-December/012670.html
Patch descriptions are available at these links, and just in case here's a copy:
advanced_bootmenu: up to 35 entries (2 pages if >18), numpad support (console)
Add support for up to 35 boot menu entries (2 pages if >18). To solve the ">10" problem currently experienced by SeaBIOS users (there are no 11, 12, etc. keys on a keyboard - so impossible to choose the last menu entries if you got
10 entries because of multiple hard drives / secondary payloads / floppies)
- the boot menu has been extended to the letter keys. NOTE: TPM menu has been moved from T to M letter: it is at the end of keyboard's 3rd row of letters and "Trusted" is adjective while "Module" is a noun; alternatively could press '-'.
Also, add support for a numpad. Small USB numpad could be really convenient for choosing the boot entries at coreboot boards used as (maybe headless) servers. '/' char on numpad could be used to open the boot menu or to exit it. If there are >10 boot menu entries - the numpad console interface will be enabled: press one or two digit keys and then ENTER to confirm your choice, or remove a digit by pressing the '.Del' key. Also you could call TPM with '-' key at any moment, or boot with a single key press of your fullsize keyboard.
[PATCH v2] ramdisk: search for all available floppy images instead of one
All the floppy images available at CBFS will be found and listed in a boot menu, instead of the first found. Could be highly valuable if you are participating in a hobby OS development - would like to test multiple versions of your floppy at the same coreboot image, to reduce the amount of re-flashes and accelerate the development at bare metal - or simply you would like to access multiple floppies as a coreboot user. For example: KolibriOS (nice assembly OS with GUI and apps), FreeDOS, MichalOS, Snowdrop and memtest (coreboot's memtest version is buggy, e.g. external USB keyboard isn't working at some laptops; floppy is much better)
Signed-off-by: Mike Banon mikebdp2@gmail.com Change-Id: Idf4efba31091a8678b51c2f6541d440c5cc6d37d --- M payloads/external/SeaBIOS/Makefile A payloads/external/SeaBIOS/advanced_bootmenu.patch A payloads/external/SeaBIOS/multiple_floppies.patch 3 files changed, 551 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/51/32351/1
diff --git a/payloads/external/SeaBIOS/Makefile b/payloads/external/SeaBIOS/Makefile index e505c8c..ae58c8c 100644 --- a/payloads/external/SeaBIOS/Makefile +++ b/payloads/external/SeaBIOS/Makefile @@ -76,7 +76,18 @@ # echo "# CONFIG_SMBIOS is not set" >> seabios/.config $(MAKE) -C seabios olddefconfig OUT=out/
-build: config +patch: + if [ -d seabios ]; then \ + cd seabios; \ + if [ ! -f .patched ]; then \ + echo " PATCH SeaBIOS $(TAG-y)"; \ + patch -p1 < ./../advanced_bootmenu.patch; \ + patch -p1 < ./../multiple_floppies.patch; \ + touch .patched; \ + fi; \ + fi + +build: config patch echo " MAKE SeaBIOS $(TAG-y)" $(MAKE) -C seabios OUT=out/
diff --git a/payloads/external/SeaBIOS/advanced_bootmenu.patch b/payloads/external/SeaBIOS/advanced_bootmenu.patch new file mode 100644 index 0000000..c914588 --- /dev/null +++ b/payloads/external/SeaBIOS/advanced_bootmenu.patch @@ -0,0 +1,332 @@ +diff --git a/src/boot.c b/src/boot.c +index 9f82f3c..f94dd27 100644 +--- a/src/boot.c ++++ b/src/boot.c +@@ -463,6 +463,7 @@ get_keystroke(int msec) + * Boot menu and BCV execution + ****************************************************************/ + ++#define BOOTMENU_PAGE_SIZE 18 + #define DEFAULT_BOOTMENU_WAIT 2500 + + // Show IPL option menu. +@@ -478,59 +479,282 @@ interactive_bootmenu(void) + ; + + char *bootmsg = romfile_loadfile("etc/boot-menu-message", NULL); +- int menukey = romfile_loadint("etc/boot-menu-key", 1); +- printf("%s", bootmsg ?: "\nPress ESC for boot menu.\n\n"); ++ int menukey = romfile_loadint("etc/boot-menu-key", 1); // custom menukey ++ printf("%s", bootmsg ?: "\nPress ESC or \ / slash for boot menu.\n\n"); + free(bootmsg); + + u32 menutime = romfile_loadint("etc/boot-menu-wait", DEFAULT_BOOTMENU_WAIT); + enable_bootsplash(); + int scan_code = get_keystroke(menutime); + disable_bootsplash(); +- if (scan_code != menukey) ++ if (scan_code != menukey && // custom menukey ++ scan_code != 1 && // ESC ++ scan_code != 43 && // '' char on keyboard ++ scan_code != 53 && // '/' char on keyboard ++ scan_code != 98) { // '/' char on numpad ++ if (scan_code == -1) ++ printf("No key pressed.\n"); ++ else ++ printf("Not a menukey pressed.\n"); + return; ++ } + + while (get_keystroke(0) >= 0) + ; + +- printf("Select boot device:\n\n"); + wait_threads(); + +- // Show menu items ++ char keyboard_keys[35] = {'1','2','3','4','5','6','7','8','9','0', ++ 'q','w','e','r','t','y','u','i','o','p', ++ 'a','s','d','f','g','h','j','k','l', ++ 'z','x','c','v','b','n'}; /* m = TPM */ ++ int numpad_scancodes[10] = { 82, 79, 80, 81, 75, 76, 77, 71, 72, 73 }; ++ int numpi = 0; // Key index: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. ++ int digits = 0; // Numerical length of a current choice number. ++ int decode = 0; // Decode the current choice number into a letter? ++ int entry_id = 0; ++ char desc[77]; ++ ++ printf("Select boot device"); ++ ++ // Show menu items after counting them and determining a number of pages. ++ // Only 35 boot menu items (36 if to count a TPM) are supported currently. ++ + int maxmenu = 0; + struct bootentry_s *pos; +- hlist_for_each_entry(pos, &BootList, node) { +- char desc[77]; ++ hlist_for_each_entry(pos, &BootList, node) + maxmenu++; +- printf("%d. %s\n", maxmenu ++ ++ if (maxmenu > 10) { ++ if (maxmenu > 35) ++ maxmenu = 35; ++ if (maxmenu > BOOTMENU_PAGE_SIZE) ++ printf(" - page 1 :"); ++ else ++ printf(": "); ++ printf(" // press ENTER after your numpad input"); ++ if (maxmenu > BOOTMENU_PAGE_SIZE) ++ printf(" - if any -\n " ++ " // - or to switch between the pages...\n"); ++ else ++ printf(" (if any)\n\n"); ++ } else { ++ printf(":\n\n"); ++ } ++ ++ hlist_for_each_entry(pos, &BootList, node) { ++ if (entry_id == BOOTMENU_PAGE_SIZE) // Show only the first page. ++ break; ++ printf("%c. %s\n", keyboard_keys[entry_id] + , strtcpy(desc, pos->description, ARRAY_SIZE(desc))); ++ entry_id++; + } ++ int tpm_cshm = 0; + if (tpm_can_show_menu()) { +- printf("\nt. TPM Configuration\n"); ++ tpm_cshm = 1; ++ printf("\nm-. TPM Configuration"); + } +- +- // Get key press. If the menu key is ESC, do not restart boot unless +- // 1.5 seconds have passed. Otherwise users (trained by years of +- // repeatedly hitting keys to enter the BIOS) will end up hitting ESC +- // multiple times and immediately booting the primary boot device. +- int esc_accepted_time = irqtimer_calc(menukey == 1 ? 1500 : 0); ++ printf("\n> "); ++ ++ // Do not restart boot on menukey press, unless DEFAULT_BOOTMENU_WAIT msecs ++ // have passed. Otherwise users (trained by years of repeatedly hitting keys ++ // to enter the BIOS) will end up hitting menukey multiple times and ++ // immediately booting the primary boot device. ++ int esc_accepted_time = irqtimer_calc(DEFAULT_BOOTMENU_WAIT); ++ int choice = 0, kb_choice = 0; ++ int page_num = 1; ++ int enter = 0; ++ int backspace = 0; ++ int tpm_show_menu = 0; + for (;;) { + scan_code = get_keystroke(1000); +- if (scan_code == 1 && !irqtimer_check(esc_accepted_time)) +- continue; +- if (tpm_can_show_menu() && scan_code == 20 /* t */) { ++ if (scan_code == menukey || // custom menukey ++ scan_code == 1 || // ESC ++ scan_code == 43 || // '' char on keyboard ++ scan_code == 53 || // '/' char on keyboard ++ scan_code == 98) { // '/' char on numpad ++ if (!irqtimer_check(esc_accepted_time)) ++ continue; ++ if (digits == 2) // Remove the decoded "(*)" ++ printf(" \b\b\b"); ++ /* Remove the existing input before printing a message. */ ++ for (; digits > 0; digits--) ++ printf("\b \b"); ++ printf("Menukey pressed.\n"); ++ return; ++ } ++ kb_choice = 0; ++ /* 4 rows of keyboard_keys: 1 row with numbers, 3 rows with letters. ++ Use any of them to select a boot device (except the TPM 'm-' keys) */ ++ // 1st range: 1-9 and 0 (10) keys <==> 2-11 scan codes <==> 1-10 choice ++ if (scan_code >= 2 && scan_code <= 11) kb_choice = scan_code - 1; ++ // 2nd range: Q-P row of letters <==> 16-25 scan codes <==> 11-20 choice ++ if (scan_code >= 16 && scan_code <= 25) kb_choice = scan_code - 5; ++ // 3rd range: A-L row of letters <==> 30-38 scan codes <==> 21-29 choice ++ if (scan_code >= 30 && scan_code <= 38) kb_choice = scan_code - 9; ++ // 4th range: Z-N row of letters <==> 44-49 scan codes <==> 30-35 choice ++ if (scan_code >= 44 && scan_code <= 49) kb_choice = scan_code - 14; ++ // ENTER: (28) on keyboard, (96) on numpad. ++ if (scan_code == 28 || scan_code == 96) ++ enter = 1; ++ // BCKSPC: '<-'(14) and 'Delete'(111) on keyboard, '.Del'(83) on numpad. ++ if (scan_code == 14 || scan_code == 111 || scan_code == 83) ++ backspace = 1; ++ // TPM keys: 'm'(50) and '-'(12) chars on keyboard, '-'(74) on numpad. ++ if ((scan_code == 50 || scan_code == 12 || scan_code == 74) && tpm_cshm) ++ tpm_show_menu = 1; ++ ++ if (kb_choice != 0 || tpm_show_menu) { ++ if (kb_choice > maxmenu) { ++ if (!tpm_show_menu) ++ continue; ++ } else { ++ choice = kb_choice; ++ } ++ if (digits == 2) // Remove the decoded "(*)" ++ printf(" \b\b\b"); ++ /* Remove the existing input before printing a choice. */ ++ for (; digits > 0; digits--) ++ printf("\b \b"); ++ if (!tpm_show_menu) { ++ // Choice is any of the detected boot devices ==> lets boot! ++ break; ++ } ++ } else { ++ // Internal/USB Numpad console interface. ++ if (digits < 9) { ++ for (numpi = 0; numpi < 10; numpi++) { ++ if (scan_code == numpad_scancodes[numpi]) { ++ if (maxmenu <= 10) { // Console interface is not needed. ++ if ((numpi != 0 && numpi <= maxmenu) || ++ (numpi == 0 && 10 <= maxmenu)) { // 10(0) ++ choice = numpi; ++ enter = 1; // Fake ENTER to boot this entry now. ++ } else { // If no such an entry, don't try to boot. ++ break; ++ } ++ } else { ++ if (digits == 2) { ++ printf(" \b\b\b"); // Remove the decoded "(*)" ++ if (choice == 0) { ++ printf("\b\b \b\b"); // Remove "10". ++ digits = 0; ++ } ++ } ++ choice = 10 * choice + numpi; ++ } ++ if (choice > 0) { ++ printf("%d", numpi); // Print the entered digit. ++ digits++; ++ } else { ++ if (10 <= maxmenu) ++ printf("10(0)\b\b\b"); ++ else ++ printf("10(?)\b\b\b"); ++ digits = 2; ++ } ++ if (choice > 9 && digits == 2) // Decode into a letter. ++ decode = 1; ++ break; ++ } ++ } ++ } ++ if (backspace && digits > 0) { ++ backspace = 0; ++ choice = choice / 10; ++ if (digits == 2) { ++ printf(" \b\b\b"); // Remove the decoded "(*)" ++ // 0 turned into 10: one more Backspace is needed to remove. ++ if (choice == 0) { ++ printf("\b \b"); ++ digits--; ++ } ++ } ++ printf("\b \b"); // Remove the last entered digit. ++ digits--; ++ if (choice > 9 && digits == 2) // Decode into a letter. ++ decode = 1; ++ } ++ if (decode) { // Decode the current choice number into a letter. ++ decode = 0; ++ if (choice <= maxmenu) { ++ printf("(%c)", keyboard_keys[choice-1]); ++ } else { ++ if (tpm_cshm && choice == 36) ++ printf("(m)"); // For TPM. ++ else ++ printf("(?)"); // No matching letter found. ++ } ++ printf("\b\b\b"); // Move a cursor before the "(*)" ++ } ++ } ++ ++ if (enter) { ++ enter = 0; ++ if (choice == 0) { ++ if (digits == 2) { // for 0 that turned into 10 ++ if (10 <= maxmenu) ++ break; ++ else ++ continue; ++ } ++ // If there are two pages - switch between them. ++ if (maxmenu > BOOTMENU_PAGE_SIZE) { ++ entry_id = 0; ++ page_num = 3 - page_num; // 3 - 1 = 2; 3 - 2 = 1. ++ printf("\n\nSelect boot device - page %d :" ++ " // press ENTER after your numpad input" ++ " - if any -\n " ++ " // - or to switch between the pages...\n", ++ page_num); ++ hlist_for_each_entry(pos, &BootList, node) { ++ if ((page_num == 1 && entry_id == BOOTMENU_PAGE_SIZE) || ++ (page_num == 2 && entry_id == 35)) ++ break; ++ if (page_num == 1 || entry_id >= BOOTMENU_PAGE_SIZE) ++ printf("%c. %s\n", keyboard_keys[entry_id], ++ strtcpy(desc, pos->description, ARRAY_SIZE(desc))); ++ entry_id++; ++ } ++ if (tpm_cshm) ++ printf("\nm-. TPM Configuration"); ++ printf("\n> "); ++ } ++ } else { ++ if (choice > maxmenu) { ++ if (tpm_cshm && choice == 36) ++ tpm_show_menu = 1; ++ } else { ++ // Choice is any of the detected boot devices ==> lets boot! ++ break; ++ } ++ } ++ } ++ ++ if (tpm_show_menu) { ++ tpm_show_menu = 0; ++ choice = 0; ++ if (digits == 0) ++ printf("TPM key pressed."); ++ else ++ digits = 0; + printf("\n"); + tpm_menu(); ++ printf("> "); + } +- if (scan_code >= 1 && scan_code <= maxmenu+1) +- break; ++ } ++ ++ if (choice == 0) // 10(0) ++ choice = 10; ++ ++ if (digits == 0 && choice < 36) { ++ printf("%c", keyboard_keys[choice-1]); ++ if (choice > 9) // Decode into a number. ++ printf("(%d)", choice); + } + printf("\n"); +- if (scan_code == 0x01) +- // ESC +- return; + + // Find entry and make top priority. +- int choice = scan_code - 1; + hlist_for_each_entry(pos, &BootList, node) { + if (! --choice) + break; +diff --git a/src/config.h b/src/config.h +index 93c8dbc..f85cc14 100644 +--- a/src/config.h ++++ b/src/config.h +@@ -19,7 +19,7 @@ + // Space to reserve in high-memory for tables + #define BUILD_MAX_HIGHTABLE (256*1024) + // Largest supported externaly facing drive id +-#define BUILD_MAX_EXTDRIVE 16 ++#define BUILD_MAX_EXTDRIVE 36 + // Number of bytes the smbios may be and still live in the f-segment + #define BUILD_MAX_SMBIOS_FSEG 600 + // Maximum number of bytes the mptable may be and still be copied to f-segment diff --git a/payloads/external/SeaBIOS/multiple_floppies.patch b/payloads/external/SeaBIOS/multiple_floppies.patch new file mode 100644 index 0000000..5249394 --- /dev/null +++ b/payloads/external/SeaBIOS/multiple_floppies.patch @@ -0,0 +1,207 @@ +diff --git a/src/block.h b/src/block.h +index f64e880..aaa236f 100644 +--- a/src/block.h ++++ b/src/block.h +@@ -2,7 +2,7 @@ + #define __BLOCK_H + + #include "types.h" // u32 +- ++#include "romfile.h" // struct romfile_s + + /**************************************************************** + * Disk command request +@@ -48,6 +48,7 @@ struct drive_s { + struct drive_s { + u8 type; // Driver type (DTYPE_*) + u8 floppy_type; // Type of floppy (only for floppy drives). ++ struct romfile_s *floppy_file; // Floppy file (only for virtual floppies). + struct chs_s lchs; // Logical CHS + u64 sectors; // Total sectors count + u32 cntl_id; // Unique id for a given driver type. +diff --git a/src/boot.c b/src/boot.c +index 9f82f3c..79f1e7d 100644 +--- a/src/boot.c ++++ b/src/boot.c +@@ -584,7 +584,7 @@ bcv_prepboot(void) + break; + case IPL_TYPE_FLOPPY: + map_floppy_drive(pos->drive); +- add_bev(IPL_TYPE_FLOPPY, 0); ++ add_bev(IPL_TYPE_FLOPPY, (u32)pos->drive); + break; + case IPL_TYPE_HARDDISK: + map_hd_drive(pos->drive); +@@ -733,6 +733,12 @@ do_boot(int seq_nr) + static void + do_boot(int seq_nr) + { ++ ++ int ret; ++ void *pos; ++ struct romfile_s *file; ++ struct drive_s *drive; ++ + if (! CONFIG_BOOT) + panic("Boot support not compiled in.\n"); + +@@ -744,6 +750,16 @@ do_boot(int seq_nr) + switch (ie->type) { + case IPL_TYPE_FLOPPY: + printf("Booting from Floppy...\n"); ++ drive = (struct drive_s *)ie->vector; ++ file = drive->floppy_file; ++ // File is NULL if a floppy is physical. ++ if (file) { ++ // Copy virtual floppy image into ram. ++ pos = (void *)drive->cntl_id; ++ ret = file->copy(file, pos, file->size); ++ if (ret < 0) ++ break; ++ } + boot_disk(0x00, CheckFloppySig); + break; + case IPL_TYPE_HARDDISK: +diff --git a/src/hw/floppy.c b/src/hw/floppy.c +index 9e6647d..5b37c6c 100644 +--- a/src/hw/floppy.c ++++ b/src/hw/floppy.c +@@ -107,7 +107,7 @@ struct floppyinfo_s FloppyInfo[] VARFSEG = { + }; + + struct drive_s * +-init_floppy(int floppyid, int ftype) ++init_floppy(int floppyid, int ftype, struct romfile_s *ffile) + { + if (ftype <= 0 || ftype >= ARRAY_SIZE(FloppyInfo)) { + dprintf(1, "Bad floppy type %d\n", ftype); +@@ -124,6 +124,7 @@ init_floppy(int floppyid, int ftype) + drive->type = DTYPE_FLOPPY; + drive->blksize = DISK_SECTOR_SIZE; + drive->floppy_type = ftype; ++ drive->floppy_file = ffile; + drive->sectors = (u64)-1; + + memcpy(&drive->lchs, &FloppyInfo[ftype].chs +@@ -134,7 +135,7 @@ addFloppy(int floppyid, int ftype) + static void + addFloppy(int floppyid, int ftype) + { +- struct drive_s *drive = init_floppy(floppyid, ftype); ++ struct drive_s *drive = init_floppy(floppyid, ftype, 0); + if (!drive) + return; + char *desc = znprintf(MAXDESCSIZE, "Floppy [drive %c]", 'A' + floppyid); +diff --git a/src/hw/ramdisk.c b/src/hw/ramdisk.c +index b9e9baa..a679385 100644 +--- a/src/hw/ramdisk.c ++++ b/src/hw/ramdisk.c +@@ -23,40 +23,69 @@ ramdisk_setup(void) + if (!CONFIG_FLASH_FLOPPY) + return; + +- // Find image. +- struct romfile_s *file = romfile_findprefix("floppyimg/", NULL); +- if (!file) +- return; +- const char *filename = file->name; +- u32 size = file->size; +- dprintf(3, "Found floppy file %s of size %d\n", filename, size); +- int ftype = find_floppy_type(size); +- if (ftype < 0) { +- dprintf(3, "No floppy type found for ramdisk size\n"); ++ struct romfile_s *file = NULL; ++ char *filename, *desc; ++ u32 size, max_size = 0; ++ int ftype; ++ void *pos; ++ struct drive_s *drive; ++ ++ // Find the max floppy size ++ for (;;) { ++ // Find the next image. ++ file = romfile_findprefix("floppyimg/", file); ++ if (!file) ++ break; ++ filename = file->name; ++ size = file->size; ++ dprintf(3, "Found floppy file %s of size %d\n", filename, size); ++ // Check if this size is valid. ++ ftype = find_floppy_type(size); ++ if (ftype < 0) { ++ dprintf(3, "No floppy type found for ramdisk size\n"); ++ } else { ++ if (size > max_size) ++ max_size = size; ++ } ++ } ++ if (max_size == 0) { ++ dprintf(3, "No floppies found\n"); + return; + } + + // Allocate ram for image. +- void *pos = memalign_tmphigh(PAGE_SIZE, size); ++ pos = memalign_tmphigh(PAGE_SIZE, max_size); + if (!pos) { + warn_noalloc(); + return; + } +- e820_add((u32)pos, size, E820_RESERVED); ++ e820_add((u32)pos, max_size, E820_RESERVED); ++ dprintf(3, "Allocate %u bytes for a floppy\n", max_size); + +- // Copy image into ram. +- int ret = file->copy(file, pos, size); +- if (ret < 0) +- return; +- +- // Setup driver. +- struct drive_s *drive = init_floppy((u32)pos, ftype); +- if (!drive) +- return; +- drive->type = DTYPE_RAMDISK; +- dprintf(1, "Mapping floppy %s to addr %p\n", filename, pos); +- char *desc = znprintf(MAXDESCSIZE, "Ramdisk [%s]", &filename[10]); +- boot_add_floppy(drive, desc, bootprio_find_named_rom(filename, 0)); ++ // Setup the floppy drivers. ++ file = NULL; ++ for (;;) { ++ // Find the next image. ++ file = romfile_findprefix("floppyimg/", file); ++ if (!file) ++ return; ++ filename = file->name; ++ size = file->size; ++ dprintf(3, "Found floppy file %s of size %d\n", filename, size); ++ ftype = find_floppy_type(size); ++ if (ftype < 0) { ++ dprintf(3, "No floppy type found for ramdisk size\n"); ++ } else { ++ // Setup driver. ++ drive = init_floppy((u32)pos, ftype, file); ++ if (!drive) ++ return; ++ drive->type = DTYPE_RAMDISK; ++ dprintf(1, "Mapping floppy %s to addr %p\n", filename, pos); ++ desc = znprintf(MAXDESCSIZE, "Ramdisk [%s]", &filename[10]); ++ boot_add_floppy(drive, desc, bootprio_find_named_rom(filename, 0)); ++ } ++ } + } + + static int +diff --git a/src/util.h b/src/util.h +index 9c06850..ce3a26d 100644 +--- a/src/util.h ++++ b/src/util.h +@@ -147,7 +147,8 @@ void dma_setup(void); + // hw/floppy.c + extern struct floppy_ext_dbt_s diskette_param_table2; + void floppy_setup(void); +-struct drive_s *init_floppy(int floppyid, int ftype); ++extern struct romfile_s *ffile; ++struct drive_s *init_floppy(int floppyid, int ftype, struct romfile_s *ffile); + int find_floppy_type(u32 size); + int floppy_process_op(struct disk_op_s *op); + void floppy_tick(void);