Skip to content

Commit d6243e0

Browse files
authored
Boot UEFI Windows (UEFI Support + ACPI + 8GB RAM) (#708)
# PR: Add UEFI/OVMF boot support (fw_cfg + dynamic ACPI) and robust >3GB RAM handling ## Summary This change set enables booting modern UEFI guests (including Windows Server 2025) under Bochs using OVMF by adding a QEMU-compatible `fw_cfg` device and generating the ACPI tables firmware expects. In the same work, it hardens/clarifies >3GB RAM behavior by introducing a PCI/MMIO “hole” at 3–4GB with RAM remapped above 4GB, and centralizes the address translation so memory accesses remain correct and safe. A key constraint throughout is **BIOS-safe defaults**: all UEFI/OVMF behavior is **opt-in** and gated by the `fw_cfg: enabled=1` configuration. ## Motivation - The target `servercore2025.vhd` (Windows Server Core 2025, UEFI install) boots under QEMU/Hyper-V but historically did not boot under Bochs. - OVMF expects: - QEMU-like `fw_cfg` to provide E820 and ACPI tables - a modern ACPI environment (RSDP/XSDT/FADT/FACS/DSDT/MADT/HPET) - sane PCI/MMIO layout (including a reserved MMIO window and correct memory reporting) ## User-facing changes ### New `fw_cfg` option (UEFI/OVMF support) - New bochsrc stanza: - `fw_cfg: enabled=1` - When enabled, Bochs exposes a QEMU-compatible `fw_cfg` interface at I/O ports **0x510–0x51B** (including the DMA interface used by OVMF). - The device provides to firmware: - E820 memory map (including a reserved 3–4GB PCI/MMIO hole) - ACPI tables (RSDP, XSDT, FADT, FACS, DSDT, MADT, HPET) - RAM size and CPU count ### OVMF usage Minimal UEFI boot configuration example: ``` romimage: file=OVMF.fd, address=0 fw_cfg: enabled=1 pci: enabled=1, chipset=i440fx, slot1=pcivga ``` ### Increased max host memory setting - The configuration option for “host allocated memory size” now allows up to **8192 MB** (previously **2048 MB**) to support larger-guest testing. ## Core implementation details ### fw_cfg device (QEMU-compatible) - Adds a new core plugin implementing the `fw_cfg` selector/data/DMA protocol. - Exposes firmware-facing blobs (E820 + ACPI tables) via the fw_cfg file interface. ### Dynamic ACPI table generation - Introduces runtime-generated ACPI table blobs aligned with the default i440fx/PIIX device model. - Uses an embedded AML blob for DSDT. ### DSDT AML generation and reproducibility - `bochs/iodev/acpi_dsdt_aml.h` is a **generated** artifact embedding the compiled AML for the Bochs DSDT. - Regeneration script: - `bochs/tools/gen_acpi_dsdt_aml.py` - Requires ACPICA `iasl` (available on PATH or passed via `--iasl`). - Temporary outputs from regeneration are ignored via `.gitignore` (e.g. `bochs/tools/_acpi_dsdt_aml.*`). ### >3GB RAM / PCI hole handling - Adds a well-defined PCI/MMIO hole at **3–4GB**. - RAM that would otherwise occupy 3–4GB is remapped above 4GB. - Introduces/uses a shared helper (`bx_translate_gpa_to_linear()`) so physical memory operations remain correct across the remap. ### Safety: direct host-pointer access in the PCI/MMIO hole - The PCI/MMIO hole is treated as “no direct host pointer” by default to avoid incorrect aliasing into RAM backing store. - A narrow exception is allowed for ROM-backed fetches in the BIOS/UEFI ROM window (required for reset-vector fetch correctness) while keeping MMIO safety guarantees. ### Reset semantics (BIOS-safe by default) - `fw_cfg` is loaded only when `fw_cfg: enabled=1`. - On **hardware reset** and only when UEFI is enabled, memory resets/reloads ROM images because OVMF may modify ROM contents during execution. - Device reset behavior was audited where startup invokes `reset()` to ensure BIOS behavior is not accidentally altered. ## Other correctness/compatibility improvements (touched by this PR) - CPU reset correctness: clears additional state, invokes mode-change handlers, and flushes TLB at reset. - MSR compatibility: adds `MSR_PLATFORM_ID` and returns 0 on read. - VGA/UEFI graphics: adds QEMU-compatible VBE BAR2 mapping used by OVMF QemuVideoDxe. - Several devices gained/reset-aligned initialization to keep init/reset consistent: - keyboard controller, serial, ATA controller state, PIC/PIT, DMA I/O width robustness. ## Documentation updates - User documentation updated with: - how to configure OVMF + `fw_cfg` - how the embedded DSDT AML is produced and how to regenerate it - note that OVMF graphics works best with `pci: ... slot1=pcivga` - `CHANGES` updated with new features and the increased max host memory setting. ## Testing - BIOS smoke test: confirmed legacy BIOS boot still works with default settings. - UEFI smoke test: confirmed OVMF boots and provides visible output with `fw_cfg` enabled and PCI VGA (`pcivga`). - Target OS coverage: tested with `servercore2025.vhd` under OVMF to exercise the UEFI boot path (fw_cfg + ACPI + PCI-hole memory map). ## Files changed (by area) ### New files - `bochs/iodev/fw_cfg.cc`, `bochs/iodev/fw_cfg.h` (fw_cfg device) - `bochs/iodev/acpi_tables.cc`, `bochs/iodev/acpi_tables.h` (dynamic ACPI) - `bochs/iodev/acpi_dsdt_aml.h` (generated AML blob) - `bochs/tools/gen_acpi_dsdt_aml.py` (DSDT regen helper) ### Updated files - Configuration and docs: - `.gitattributes`, `.gitignore` - `bochs/CHANGES` - `bochs/config.cc` - `bochs/doc/docbook/user/user.dbk` - Core plumbing: - `bochs/plugin.h`, `bochs/plugin.cc`, `bochs/param_names.h` - `bochs/cpu/init.cc`, `bochs/cpu/msr.cc`, `bochs/cpu/msr.h` - `bochs/memory/memory-bochs.h`, `bochs/memory/memory.cc`, `bochs/memory/memory_stub.cc`, `bochs/memory/misc_mem.cc` - Devices: - `bochs/iodev/devices.cc`, `bochs/iodev/acpi.cc`, `bochs/iodev/hpet.cc` - `bochs/iodev/display/vga.cc`, `bochs/iodev/display/vga.h` - `bochs/iodev/dma.cc`, `bochs/iodev/pic.cc`, `bochs/iodev/pit82c54.cc` - `bochs/iodev/keyboard.cc`, `bochs/iodev/serial.cc`, `bochs/iodev/serial.h`, `bochs/iodev/harddrv.cc` ## Notes / follow-ups - This PR intentionally keeps UEFI support **opt-in** to avoid changing the default BIOS behavior. - The DSDT AML is committed as a generated artifact to avoid a build-time dependency on ACPICA; the provided script documents how to regenerate it deterministically. - `.gitignore` shows a large diff primarily due to line-ending normalization (LF) plus a small number of new ignore patterns for local test artifacts and the DSDT regeneration temporary outputs. ## Sample UEFI BXRC: ``` # Minimal UEFI smoke config (fw_cfg enabled) plugin_ctrl: unmapped=1, biosdev=1, speaker=0, serial=1, parallel=0, gameport=0, e1000=0, extfpuirq=1 config_interface: textconfig display_library: win32 memory: host=4096, guest=4096 # OVMF firmware romimage: file="e:/tmp/VSCODE_PROJ2/RELEASEX64_OVMF.fd", address=0x0, options=none vgaromimage: file="e:/tmp/bochs_upstream/bochs/bios/VGABIOS-lgpl-latest.bin" # UEFI boot requires fw_cfg fw_cfg: enabled=1 boot: disk floppy_bootsig_check: disabled=0 ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 ata0-master: type=disk, path="e:/tmp/VSCODE_PROJ2/servercore2025.vhd", mode=vpc ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 ata1-master: type=none ata1-slave: type=none ata2: enabled=0 ata3: enabled=0 # UEFI GOP/video init expects VGA as a PCI device pci: enabled=1, chipset=i440fx, slot1=pcivga vga: extension=vbe, update_freq=60, realtime=1 cpu: count=1, ips=100000000, model=corei7_sandy_bridge_2600k, reset_on_triple_fault=0, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=1 print_timestamps: enabled=0 port_e9_hack: enabled=0 private_colormap: enabled=0 clock: sync=none, time0=local, rtc_sync=0 log: e:/tmp/VSCODE_PROJ2/bochsout_smoke_uefi.txt logprefix: %t%e%d debug: action=ignore info: action=report error: action=report panic: action=report # OVMF debug output com1: enabled=1, mode=file, dev=e:/tmp/VSCODE_PROJ2/serial_smoke_uefi.log keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=ctrl-alt-del mouse: type=ps2, enabled=0, toggle=ctrl+mbutton ```
1 parent 190e6b8 commit d6243e0

File tree

29 files changed

+2789
-102
lines changed

29 files changed

+2789
-102
lines changed

.gitattributes

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
* text=auto eol=lf
2-
configure binary
2+
configure binary
3+
4+
# Explicitly enforce LF on frequently-edited generated/interop files.
5+
bochs/iodev/fw_cfg.cc text eol=lf
6+
bochs/iodev/fw_cfg.h text eol=lf
7+
bochs/iodev/acpi_dsdt_aml.h text eol=lf

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ bochs-msvc-src.zip
4747
/bochs/bios/rombios*.txt
4848
/bochs/bios/rombios*.bin
4949
/bochs/bios/rombios32.out
50+
/bochs/bios/acpi-dsdt-preprocessed.*
51+
52+
# ACPI DSDT generation temporary outputs (bochs/tools/gen_acpi_dsdt_aml.py)
53+
/bochs/tools/_acpi_dsdt_aml.*
5054

5155
# /bochs/build/linux/
5256
/bochs/build/linux/DOC-linux.html

bochs/CHANGES

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,33 @@ Detailed change log :
3434
- Config interface
3535
- On Windows make sure file name parameters use backslash as separator
3636
- Removed backward compatibility mode for USB device options
37+
- Increased maximum host memory size to 8192 MB (was 2048 MB)
3738

3839
- Memory
40+
- PCI hole support for >3GB RAM (NEW)
41+
Added guest physical address translation for systems with more than 3GB RAM.
42+
RAM from 3GB-4GB is remapped above 4GB to make room for PCI MMIO space.
43+
The bx_translate_gpa_to_linear() helper handles the remapping transparently.
44+
Works correctly with 2GB, 4GB, 8GB, 12GB, 16GB, and larger RAM configurations.
45+
3946
- Added support for overlapping r/o memory handlers (used for PCI ROM)
4047
- Added support for mapping PCI ROM to expansion ROM space
4148

4249
- I/O Devices
50+
- fw_cfg (NEW)
51+
Added QEMU-compatible fw_cfg device for UEFI/OVMF firmware support.
52+
Provides system configuration to firmware via I/O ports 0x510-0x51B:
53+
- E820 memory map with PCI hole (3GB-4GB reserved for MMIO)
54+
- ACPI tables (RSDP, XSDT, FADT, FACS, DSDT, MADT, HPET)
55+
- RAM size and CPU count information
56+
- DMA protocol for table loading
57+
This enables booting UEFI operating systems including Windows Server 2025
58+
and modern Linux distributions with OVMF firmware.
59+
- ACPI Tables
60+
Added dynamic ACPI table generation for UEFI firmware compatibility.
61+
Tables are compatible with PIIX4 PM/ACPI and include proper DSDT.
62+
The generated DSDT is aligned with the default PCI/PIIX device model.
63+
4364
- GeForce (NEW)
4465
Added basic support for three GeForce models. Most of the 2D features are present,
4566
but 3D is still WIP. Several Windows versions up to Win 7 have been reported to
@@ -3133,7 +3154,7 @@ Detailed change log :
31333154
[1021758] GNU/k*BSD host support by Robert Millan
31343155
[969967] int 15/ah=87h clearing cr0 by Ben Lunt
31353156
[1048327] Russian Keymap by Dmitry Soshnikov
3136-
[851332] DESTDIR support for install_dlx by Ville Skytt�
3157+
[851332] DESTDIR support for install_dlx by Ville Skytt�
31373158
[970929] gdbstub support for MinGW tool chains by Muranaka Masaki
31383159
[1021740] Turn gdb stub into a runtime option by Charles Duffy
31393160
[1063329] RFB key press/release bug fix by Remko van der Vossen

bochs/build/win32/vs2019-workspace/vs2019-plugins/iodev.vcxproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,11 +215,16 @@
215215
</Bscmake>
216216
</ItemDefinitionGroup>
217217
<ItemGroup>
218+
<ClCompile Include="..\iodev\acpi_tables.cc" />
218219
<ClCompile Include="..\iodev\devices.cc" />
220+
<ClCompile Include="..\iodev\fw_cfg.cc" />
219221
<ClCompile Include="..\iodev\slowdown_timer.cc" />
220222
<ClCompile Include="..\iodev\virt_timer.cc" />
221223
</ItemGroup>
222224
<ItemGroup>
225+
<ClInclude Include="..\iodev\acpi_dsdt_aml.h" />
226+
<ClInclude Include="..\iodev\acpi_tables.h" />
227+
<ClInclude Include="..\iodev\fw_cfg.h" />
223228
<ClInclude Include="..\iodev\iodev.h" />
224229
<ClInclude Include="..\iodev\slowdown_timer.h" />
225230
<ClInclude Include="..\iodev\virt_timer.h" />

bochs/build/win32/vs2019-workspace/vs2019/iodev.vcxproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,13 +216,15 @@
216216
</ItemDefinitionGroup>
217217
<ItemGroup>
218218
<ClCompile Include="..\iodev\acpi.cc" />
219+
<ClCompile Include="..\iodev\acpi_tables.cc" />
219220
<ClCompile Include="..\iodev\biosdev.cc" />
220221
<ClCompile Include="..\iodev\busmouse.cc" />
221222
<ClCompile Include="..\iodev\cmos.cc" />
222223
<ClCompile Include="..\iodev\devices.cc" />
223224
<ClCompile Include="..\iodev\dma.cc" />
224225
<ClCompile Include="..\iodev\extfpuirq.cc" />
225226
<ClCompile Include="..\iodev\floppy.cc" />
227+
<ClCompile Include="..\iodev\fw_cfg.cc" />
226228
<ClCompile Include="..\iodev\gameport.cc" />
227229
<ClCompile Include="..\iodev\harddrv.cc" />
228230
<ClCompile Include="..\iodev\hpet.cc" />
@@ -246,12 +248,15 @@
246248
</ItemGroup>
247249
<ItemGroup>
248250
<ClInclude Include="..\iodev\acpi.h" />
251+
<ClInclude Include="..\iodev\acpi_dsdt_aml.h" />
252+
<ClInclude Include="..\iodev\acpi_tables.h" />
249253
<ClInclude Include="..\iodev\biosdev.h" />
250254
<ClInclude Include="..\iodev\busmouse.h" />
251255
<ClInclude Include="..\iodev\cmos.h" />
252256
<ClInclude Include="..\iodev\dma.h" />
253257
<ClInclude Include="..\iodev\extfpuirq.h" />
254258
<ClInclude Include="..\iodev\floppy.h" />
259+
<ClInclude Include="..\iodev\fw_cfg.h" />
255260
<ClInclude Include="..\iodev\gameport.h" />
256261
<ClInclude Include="..\iodev\harddrv.h" />
257262
<ClInclude Include="..\iodev\hpet.h" />

bochs/config.cc

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ void bx_init_options()
726726
"host",
727727
"Host allocated memory size (megabytes)",
728728
"Amount of host allocated memory in megabytes",
729-
1, 2048,
729+
1, 8192,
730730
BX_DEFAULT_MEM_MEGS);
731731
host_ramsize->set_ask_format("Enter host memory size (MB): [%d] ");
732732
ram->set_options(ram->SERIES_ASK);
@@ -1627,6 +1627,14 @@ void bx_init_options()
16271627
"Debug messages written to i/o port 0xE9 from ring3 will be displayed on console",
16281628
0);
16291629

1630+
// fw_cfg device (UEFI/OVMF support)
1631+
bx_list_c *fw_cfg = new bx_list_c(misc, "fw_cfg", "QEMU fw_cfg device (UEFI/OVMF support)");
1632+
new bx_param_bool_c(fw_cfg,
1633+
"enabled",
1634+
"Enable fw_cfg device",
1635+
"Enables the QEMU-compatible fw_cfg device used by UEFI/OVMF firmware",
1636+
0);
1637+
16301638
#if BX_SUPPORT_IODEBUG
16311639
// iodebug all rings
16321640
new bx_param_bool_c(misc,
@@ -3188,6 +3196,12 @@ static int parse_line_formatted(const char *context, int num_params, char *param
31883196
PARSE_ERR(("%s: port_e9_hack directive malformed.", context));
31893197
}
31903198
}
3199+
} else if (!strcmp(params[0], "fw_cfg")) {
3200+
for (i=1; i<num_params; i++) {
3201+
if (bx_parse_param_from_list(context, params[i], (bx_list_c*) SIM->get_param(BXPN_FW_CFG_ROOT)) < 0) {
3202+
PARSE_ERR(("%s: fw_cfg directive malformed.", context));
3203+
}
3204+
}
31913205
} else if (!strcmp(params[0], "iodebug")) {
31923206
#if BX_SUPPORT_IODEBUG
31933207
if (num_params != 2) {
@@ -3583,6 +3597,7 @@ int bx_write_configuration(const char *rc, int overwrite)
35833597
fprintf(fp, "print_timestamps: enabled=%d\n", bx_dbg.print_timestamps);
35843598
bx_write_debugger_options(fp);
35853599
bx_write_param_list(fp, (bx_list_c*) SIM->get_param(BXPN_PORT_E9_HACK_ROOT), NULL, 0);
3600+
bx_write_param_list(fp, (bx_list_c*) SIM->get_param(BXPN_FW_CFG_ROOT), NULL, 0);
35863601
#if BX_SUPPORT_IODEBUG
35873602
fprintf(fp, "iodebug: all_rings=%d\n", SIM->get_param_bool(BXPN_IODEBUG_ALL_RINGS)->get());
35883603
#endif

bochs/doc/docbook/user/user.dbk

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3180,7 +3180,29 @@ Bochs must be set up to use system and VGA BIOS like this:
31803180
We recommend to use the ROM images distributed with Bochs or one of the latest
31813181
<ulink url="http://www.seabios.org/">SeaBIOS</ulink> images. BIOS images designed
31823182
for real hardware mostly do not work properly. Please see the <xref linkend="bochsopt-romimage">
3183-
for more information.
3183+
</para>
3184+
3185+
<para>
3186+
<emphasis>UEFI Firmware Support:</emphasis> Bochs supports UEFI boot using OVMF
3187+
(Open Virtual Machine Firmware) from the TianoCore EDK2 project. To use UEFI:
3188+
<screen>
3189+
romimage: file=OVMF.fd, address=0xffc00000
3190+
</screen>
3191+
UEFI boot requires the fw_cfg device which provides system configuration to the
3192+
firmware via I/O ports 0x510-0x51B. This includes the E820 memory map, ACPI tables,
3193+
RAM size, and CPU count. Enable it with:
3194+
<screen>
3195+
fw_cfg: enabled=1
3196+
</screen>
3197+
For best results with OVMF graphics output, configure VGA as a PCI device:
3198+
<screen>
3199+
pci: enabled=1, chipset=i440fx, slot1=pcivga
3200+
</screen>
3201+
The ACPI DSDT AML is built into Bochs and generated from the Bochs DSDT DSL
3202+
source using the ACPICA iasl compiler.
3203+
For developers, bochs/tools/gen_acpi_dsdt_aml.py can regenerate the embedded
3204+
AML header.
3205+
UEFI boot has been tested with Windows Server 2025 and modern Linux distributions.
31843206
</para>
31853207

31863208
<para>

bochs/iodev/Makefile.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ OBJS_THAT_CANNOT_BE_PLUGINS = \
7272
OBJS_THAT_CAN_BE_PLUGINS = \
7373
pic.o \
7474
pit.o \
75+
fw_cfg.o \
76+
acpi_tables.o \
7577
serial.o \
7678
parallel.o \
7779
floppy.o \

bochs/iodev/acpi.cc

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,31 @@ void bx_acpi_ctrl_c::reset(unsigned type)
162162
BX_ACPI_THIS pci_conf[0x3c] = 0x00; // IRQ
163163

164164
// PM base 0x40 - 0x43
165-
BX_ACPI_THIS pci_conf[0x40] = 0x01;
166-
BX_ACPI_THIS pci_conf[0x41] = 0x00;
167-
BX_ACPI_THIS pci_conf[0x42] = 0x00;
168-
BX_ACPI_THIS pci_conf[0x43] = 0x00;
165+
// Note: the reset default (0x0001) indicates an unconfigured PCI I/O BAR.
166+
// Do not map the ACPI I/O window at address 0x0000/0x0001.
167+
//
168+
// When running with UEFI firmware (OVMF), seed QEMU-like defaults so the
169+
// ACPI PM timer is available very early.
170+
const bool uefi_enabled = SIM->get_param_bool(BXPN_FW_CFG_ENABLED)->get();
171+
Bit32u pmbar = ReadHostDWordFromLittleEndian((Bit32u*) &BX_ACPI_THIS pci_conf[0x40]);
172+
if (!uefi_enabled) {
173+
// Upstream-compatible reset behavior.
174+
BX_ACPI_THIS pci_conf[0x40] = 0x01;
175+
BX_ACPI_THIS pci_conf[0x41] = 0x00;
176+
BX_ACPI_THIS pci_conf[0x42] = 0x00;
177+
BX_ACPI_THIS pci_conf[0x43] = 0x00;
178+
} else {
179+
if ((pmbar & 0xffc0) == 0) {
180+
// Default to 0xB000 (I/O BAR => bit0 set).
181+
BX_ACPI_THIS pci_conf[0x40] = 0x01;
182+
BX_ACPI_THIS pci_conf[0x41] = 0xB0;
183+
BX_ACPI_THIS pci_conf[0x42] = 0x00;
184+
BX_ACPI_THIS pci_conf[0x43] = 0x00;
185+
} else {
186+
// Preserve base, keep only the read-only bit semantics on the low byte.
187+
BX_ACPI_THIS pci_conf[0x40] = (BX_ACPI_THIS pci_conf[0x40] & 0xc0) | 0x01;
188+
}
189+
}
169190

170191
// clear DEVACTB register on PIIX4 ACPI reset
171192
BX_ACPI_THIS pci_conf[0x58] = 0x00;
@@ -179,10 +200,25 @@ void bx_acpi_ctrl_c::reset(unsigned type)
179200
BX_ACPI_THIS pci_conf[0x67] = 0x98;
180201

181202
// SM base 0x90 - 0x93
182-
BX_ACPI_THIS pci_conf[0x90] = 0x01;
183-
BX_ACPI_THIS pci_conf[0x91] = 0x00;
184-
BX_ACPI_THIS pci_conf[0x92] = 0x00;
185-
BX_ACPI_THIS pci_conf[0x93] = 0x00;
203+
Bit32u smbar = ReadHostDWordFromLittleEndian((Bit32u*) &BX_ACPI_THIS pci_conf[0x90]);
204+
if (!uefi_enabled) {
205+
// Upstream-compatible reset behavior.
206+
BX_ACPI_THIS pci_conf[0x90] = 0x01;
207+
BX_ACPI_THIS pci_conf[0x91] = 0x00;
208+
BX_ACPI_THIS pci_conf[0x92] = 0x00;
209+
BX_ACPI_THIS pci_conf[0x93] = 0x00;
210+
} else {
211+
if ((smbar & 0xfff0) == 0) {
212+
// Default to 0xB100 (I/O BAR => bit0 set).
213+
BX_ACPI_THIS pci_conf[0x90] = 0x01;
214+
BX_ACPI_THIS pci_conf[0x91] = 0xB1;
215+
BX_ACPI_THIS pci_conf[0x92] = 0x00;
216+
BX_ACPI_THIS pci_conf[0x93] = 0x00;
217+
} else {
218+
// Preserve base, keep only the read-only bit semantics on the low byte.
219+
BX_ACPI_THIS pci_conf[0x90] = (BX_ACPI_THIS pci_conf[0x90] & 0xf0) | 0x01;
220+
}
221+
}
186222

187223
BX_ACPI_THIS s.pmsts = 0;
188224
BX_ACPI_THIS s.pmen = 0;
@@ -203,6 +239,22 @@ void bx_acpi_ctrl_c::reset(unsigned type)
203239
for (i = 0; i < 32; i++) {
204240
BX_ACPI_THIS s.smbus.data[i] = 0;
205241
}
242+
243+
// Map the ACPI I/O windows only when the BAR is configured (non-zero base).
244+
pmbar = ReadHostDWordFromLittleEndian((Bit32u*) &BX_ACPI_THIS pci_conf[0x40]);
245+
smbar = ReadHostDWordFromLittleEndian((Bit32u*) &BX_ACPI_THIS pci_conf[0x90]);
246+
if ((pmbar & 0xffc0) != 0) {
247+
DEV_pci_set_base_io(BX_ACPI_THIS_PTR, read_handler, write_handler,
248+
&BX_ACPI_THIS s.pm_base,
249+
&BX_ACPI_THIS pci_conf[0x40],
250+
64, &acpi_pm_iomask[0], "ACPI PM base");
251+
}
252+
if ((smbar & 0xfff0) != 0) {
253+
DEV_pci_set_base_io(BX_ACPI_THIS_PTR, read_handler, write_handler,
254+
&BX_ACPI_THIS s.sm_base,
255+
&BX_ACPI_THIS pci_conf[0x90],
256+
16, &acpi_sm_iomask[0], "ACPI SM base");
257+
}
206258
}
207259

208260
void bx_acpi_ctrl_c::register_state(void)

0 commit comments

Comments
 (0)