Skip to content

Commit

Permalink
BOOT --bios: Execute the ROM BIOS after DOS kernel shutdown but do no…
Browse files Browse the repository at this point in the history
…t treat it as a system reset signal. Load the BIOS image first into a temporary buffer and do not map until it is ready to execute to avoid crashes during DOS kernel shutdown triggered by BOOT --bios
  • Loading branch information
joncampbell123 committed Feb 21, 2024
1 parent ab8aac8 commit 9c3c4a8
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 3 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
Next:
- BOOT --bios no longer triggers a system reset VM event, but instead just
jumps to the new BIOS image after DOS kernel shutdown. This is needed for
hardware and resources to stay as they were when running the BIOS i.e.
keeping any IDE devices configured within the DOS kernel intact so that the
BIOS can find and use them. Prior to this change, all hardware was fully
reset and unmapped prior to running the BIOS which made IDE emulation
unusable with BIOS images. (joncampbell123).
- BOOT --bios no longer immediately loads the new BIOS into memory, but instead
loads and stores the image to a temporary buffer. The ROM image does not
actually get mapped in until the DOS kernel and everything else has had a
chance to shut down fully. (joncampbell123).
- Fix BOOT --bios not to try to load PC-98 ITF firmware unless actually running
in PC-98 mode (joncampbell123).
- Write PC-98 keyboard translation table (non-shifted) in ROM BIOS and set the
keyboard translation table pointer in the BIOS data area for "Nut Berry".
This Nut Berry game also assumes lookup and translation tables exist at
Expand Down
13 changes: 12 additions & 1 deletion src/dos/dos_programs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1637,6 +1637,9 @@ static void CFGTOOL_ProgramStart(Program * * make) {
}

extern bool custom_bios;
extern size_t custom_bios_image_size;
extern Bitu custom_bios_image_offset;
extern unsigned char *custom_bios_image;
extern uint32_t floppytype;
extern bool boot_debug_break;
extern Bitu BIOS_bootfail_code_offset;
Expand Down Expand Up @@ -2005,7 +2008,15 @@ class BOOT : public Program {
Bitu segbase = 0x100000 - loadsz;
LOG_MSG("Loading BIOS image %s to 0x%lx, 0x%lx bytes",bios.c_str(),(unsigned long)segbase,(unsigned long)loadsz);
fseek(romfp, 0, SEEK_SET);
size_t readResult = fread(GetMemBase()+segbase,loadsz,1,romfp);

// To avoid crashes should any interrupt be called on the way to running the BIOS,
// don't actually map it in until it's good and ready to go.
if (custom_bios_image != NULL) delete[] custom_bios_image;
custom_bios_image_size = loadsz;
custom_bios_image_offset = segbase;
custom_bios_image = new unsigned char[custom_bios_image_size];

size_t readResult = fread(custom_bios_image,loadsz,1,romfp);
fclose(romfp);
if (readResult != 1) {
LOG(LOG_IO, LOG_ERROR) ("Reading error in Run\n");
Expand Down
56 changes: 54 additions & 2 deletions src/gui/sdlmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7520,6 +7520,9 @@ bool is_always_on_top(void) {
}

bool custom_bios = false;
size_t custom_bios_image_size = 0;
Bitu custom_bios_image_offset = 0;
unsigned char *custom_bios_image = NULL;

// OK why isn't this being set for Linux??
#ifndef SDL_MAIN_NOEXCEPT
Expand Down Expand Up @@ -7643,6 +7646,8 @@ std::wstring win32_prompt_folder(const char *default_folder) {
}
#endif

void CPU_OnReset(Section* sec);

void DISP2_Init(uint8_t color), DISP2_Shut();
//extern void UI_Init(void);
void grGlideShutdown(void);
Expand Down Expand Up @@ -9298,13 +9303,15 @@ int main(int argc, char* argv[]) SDL_MAIN_NOEXCEPT {
Reflect_Menu();
#endif

bool run_bios;
bool reboot_dos;
bool run_machine;
bool wait_debugger;
bool reboot_machine;
bool dos_kernel_shutdown;

fresh_boot:
run_bios = false;
reboot_dos = false;
run_machine = false;
wait_debugger = false;
Expand Down Expand Up @@ -9356,7 +9363,7 @@ int main(int argc, char* argv[]) SDL_MAIN_NOEXCEPT {
else if (x == 8) { /* Booting to a BIOS, shutting down DOSBox-X BIOS */
LOG(LOG_MISC,LOG_DEBUG)("Emulation threw a signal to boot into BIOS image");

reboot_machine = true;
run_bios = true;
dos_kernel_shutdown = !dos_kernel_disabled; /* only if DOS kernel enabled */
}
else if (x == 9) { /* BIOS caught a JMP to F000:FFF0 without any other hardware reset signal */
Expand Down Expand Up @@ -9537,7 +9544,52 @@ int main(int argc, char* argv[]) SDL_MAIN_NOEXCEPT {
Reflect_Menu();
#endif

if (reboot_machine) {
if (run_bios) {
LOG_MSG("Running a custom BIOS");

boothax = BOOTHAX_NONE;
guest_msdos_LoL = 0;
guest_msdos_mcb_chain = 0;

void CPU_Snap_Back_Forget();
/* Shutdown everything. For shutdown to work properly we must force CPU to real mode */
CPU_Snap_Back_To_Real_Mode();
CPU_Snap_Back_Forget();

/* TODO: Should we tell the system? */

/* force the mapper to let go of all keys so that the host key is not stuck (Issue #1320) */
MAPPER_ReleaseAllKeys();
void MAPPER_LosingFocus(void);
MAPPER_LosingFocus();

if (custom_bios) {
if (custom_bios_image && custom_bios_image_size != 0 && custom_bios_image_offset != 0) {
memcpy(GetMemBase()+custom_bios_image_offset,custom_bios_image,custom_bios_image_size);
}

if (custom_bios_image) delete[] custom_bios_image;

/* need to relocate BIOS allocations */
void ROMBIOS_InitForCustomBIOS(void);
ROMBIOS_InitForCustomBIOS();
}

CPU_OnReset(NULL);

#if C_DEBUG
if (boot_debug_break) {
boot_debug_break = false;

Bitu DEBUG_EnableDebugger(void);
DEBUG_EnableDebugger();
}
#endif

/* run again */
goto fresh_boot;
}
else if (reboot_machine) {
LOG_MSG("Rebooting the system\n");

boothax = BOOTHAX_NONE;
Expand Down

0 comments on commit 9c3c4a8

Please sign in to comment.