Skip to content

Commit da4becc

Browse files
committed
Release Stuff
Signed-off-by: Jiaxun Yang <[email protected]>
1 parent b840544 commit da4becc

File tree

7 files changed

+215
-8
lines changed

7 files changed

+215
-8
lines changed

.github/workflows/build.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ name: Build
22
on:
33
push:
44
pull_request:
5+
release:
6+
types: [created]
57

68
jobs:
79
build:
8-
910
runs-on: ubuntu-latest
10-
1111
steps:
1212
- uses: actions/checkout@v4
1313
- name: Install deps
@@ -18,3 +18,11 @@ jobs:
1818
with:
1919
name: csmwrap.efi
2020
path: csmwrap.efi
21+
- name: Upload release
22+
uses: actions/upload-release-asset@v1
23+
if: github.event_name == 'release'
24+
with:
25+
upload_url: ${{ github.event.release.upload_url }}
26+
asset_path: csmwrap.efi
27+
asset_name: csmwrap.efi
28+
asset_content_type: application/octet-stream

LegacyBios.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ typedef enum {
295295
/// code is read/write.
296296
/// Input:
297297
/// AX = Compatibility16PrepareToBoot
298-
/// ES:BX = Pointer to EFI_TO_COMPATIBILITY16_BOOT_TABLE structure
298+
/// ES:BX = Pointer to EFI_TO_COMPATIBILITY16_BOOT_TABLE structure
299299
/// Return:
300300
/// AX = Returned status codes
301301
///
@@ -391,7 +391,7 @@ typedef struct {
391391
UINT16 RuntimeSegment; ///< The segment where the OpROM can be relocated to. If this value is 0x0000, this
392392
///< means that the relocation of this run time code is not supported.
393393
///< Inconsistent with specification here:
394-
///< The member's name "OpromDestinationSegment" [defined in Intel Framework Compatibility Support Module Specification / 0.97 version]
394+
///< The member's name "OpromDestinationSegment" [defined in Intel Framework Compatibility Support Module Specification / 0.97 version]
395395
///< has been changed to "RuntimeSegment" since keeping backward compatible.
396396

397397
} EFI_DISPATCH_OPROM_TABLE;

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
TARGET = csmwrap.efi
2+
ARCH = x86_64
23

34
#USE_GCC=1
45
include uefi/Makefile

README.md

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,50 @@
1-
# csmwrap
2-
Get PC BIOS back on UEFI only system
1+
# CSMWrap
2+
3+
CSMWrap is a cool little hack that brings back the good old PC BIOS on those fancy-pants UEFI-only systems. It utilises the CSM (Compatibility Support Module) and VESA VBIOS from SeaBIOS Project to emulate a legacy BIOS environment.
4+
5+
## Current Status
6+
7+
Right now, CSMWrap can:
8+
9+
- Boot FreeDOS, Windows XP, and Windows 7 in QEMU (both q35 and piix4 machines)
10+
- Run on some real hardware too! (Your mileage may vary)
11+
12+
## Implementation Details
13+
14+
CSMWrap works by:
15+
16+
- Unlocking the legacy BIOS memory region (0xC0000-0xFFFFF)
17+
- Loading the SeaBIOS CSM module into memory
18+
- Configuring memory mapping for legacy applications
19+
- Setting up VGA BIOS with information from EFI GOP
20+
- Building an E820 memory map based on EFI memory map
21+
- Providing essential compatibility tables (ACPI, SMBIOS)
22+
- Initializing the CSM module and legacy services
23+
- Transferring control to the legacy boot process
24+
25+
## How to Use
26+
27+
Simply use `csmwarp.efi` as your bootloader, you can place it in your EFI partition and boot from it. Remember to disable Secure Boot, and Above 4G Decoding in your BIOS/UEFI settings.
28+
29+
## Limitations
30+
### Above 4G Decoding
31+
32+
It is almost required to run CSMWrap with above 4G decoding disabled in your BIOS/UEFI. As UEFI firmwares are likely to place GPU's VRAM BAR above 4G, and legacy BIOS are 32bit which means it can only access the first 4G of memory.
33+
34+
### Legacy Region Unlocking
35+
36+
Currently csmwrap relies on `EFI_LEGACY_REGION2_PROTOCOL` to enable writing to the legacy region. This is not available on all systems. For system that do not support this protocol, csmwrap will attempt to use PAM registers in chipset to perform decoding, which is not guaranteed to work.
37+
38+
### Windows Video Modesetting Issues
39+
40+
Windows XP/7's video modesetting logic is a bit mysterious. It may try to set a incompatible mode using `int10h`, which will cause flickering or even black screen after transferring control to the legacy OS.
41+
42+
This is a known issue and may be fixed in the future.
43+
44+
Meanwhile you can try to inject the GPU driver to OS image to avoid using the VESA BIOS.
45+
46+
## Credits
47+
- [SeaBIOS](https://www.seabios.org/) for the CSM module and VESA VBIOS
48+
- [POSIX-UEFI](https://gitlab.com/bztsrc/posix-uefi) for EFI C runtime and other useful code
49+
- [EDK2](https://github.com/tianocore/edk2) for code snippets
50+
- @CanonKong for test feedback and general knowledge

csmwrap.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
// Generated by: xxd -i vgabios.bin >> vgabios.h
1111
#include "bins/vgabios.h"
1212

13+
const char *banner = "CSMWrap\n"
14+
"https://github.com/flygoat/csmwrap\n"
15+
"By: Jiaxun Yang <[email protected]>\n";
16+
1317
#define BIOS_ROM_BASE 0xc0000
1418

1519
struct csmwrap_priv priv = {
@@ -107,12 +111,11 @@ int main(int argc, char_t **argv)
107111
uintptr_t csm_bin_base;
108112
EFI_IA32_REGISTER_SET Regs;
109113

110-
printf("Hello World!\n");
114+
printf("%s", banner);
111115

112116
BS->RaiseTPL(TPL_NOTIFY);
113117
BS->SetWatchdogTimer(0, 0, 0, NULL);
114118

115-
printf("Hello World!\n");
116119
if (unlock_bios_region()) {
117120
printf("Unable to unlock BIOS region\n");
118121
return -1;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
From c7849b92ea651c976ab0141e2b04e94ba73900d6 Mon Sep 17 00:00:00 2001
2+
From: Jiaxun Yang <[email protected]>
3+
Date: Fri, 9 May 2025 17:48:07 +0100
4+
Subject: [PATCH 1/2] csm: Setup PIC in PrepareToBoot
5+
6+
This is required to get timer working.
7+
8+
Signed-off-by: Jiaxun Yang <[email protected]>
9+
---
10+
src/fw/csm.c | 1 +
11+
1 file changed, 1 insertion(+)
12+
13+
diff --git a/src/fw/csm.c b/src/fw/csm.c
14+
index 579debdcf4cc..ccd7645e1ce9 100644
15+
--- a/src/fw/csm.c
16+
+++ b/src/fw/csm.c
17+
@@ -184,6 +184,7 @@ handle_csm_0002(struct bregs *regs)
18+
struct bios_data_area_s *bda = MAKE_FLATPTR(SEG_BDA, 0);
19+
bda->hdcount = 0;
20+
21+
+ pic_setup();
22+
thread_setup();
23+
mathcp_setup();
24+
timer_setup();
25+
--
26+
2.39.5 (Apple Git-154)
27+
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
From a32ab563d402f54d72d28f91c99fdff863f2f502 Mon Sep 17 00:00:00 2001
2+
From: Jiaxun Yang <[email protected]>
3+
Date: Thu, 9 Dec 2021 18:39:03 +0000
4+
Subject: [PATCH 2/2] Add CSM VGA service
5+
6+
Signed-off-by: Jiaxun Yang <[email protected]>
7+
---
8+
vgasrc/Kconfig | 10 +++++++++-
9+
vgasrc/cbvga.c | 43 +++++++++++++++++++++++++++++++++++++++++++
10+
vgasrc/vgahw.h | 2 ++
11+
vgasrc/vgautil.h | 1 +
12+
4 files changed, 55 insertions(+), 1 deletion(-)
13+
14+
diff --git a/vgasrc/Kconfig b/vgasrc/Kconfig
15+
index c8fac36fb92b..003f2c6a578e 100644
16+
--- a/vgasrc/Kconfig
17+
+++ b/vgasrc/Kconfig
18+
@@ -64,6 +64,14 @@ menu "VGA ROM"
19+
Build support for a vgabios wrapper around video
20+
devices initialized using coreboot native vga init.
21+
22+
+ config VGA_CSM
23+
+ depends on CSM
24+
+ bool "CSM linear framebuffer"
25+
+ select VGA_EMULATE_TEXT
26+
+ help
27+
+ Build support for a vgabios wrapper around video
28+
+ devices initialized using UEFI native vga init.
29+
+
30+
config DISPLAY_BOCHS
31+
depends on QEMU
32+
bool "qemu bochs-display support"
33+
@@ -173,7 +181,7 @@ menu "VGA ROM"
34+
Support VBE.
35+
36+
config VGA_PCI
37+
- depends on BUILD_VGABIOS && !VGA_COREBOOT
38+
+ depends on BUILD_VGABIOS && !VGA_COREBOOT && !VGA_CSM
39+
bool "PCI ROM Headers"
40+
default y
41+
help
42+
diff --git a/vgasrc/cbvga.c b/vgasrc/cbvga.c
43+
index 243e6be9459b..7e78a61348a1 100644
44+
--- a/vgasrc/cbvga.c
45+
+++ b/vgasrc/cbvga.c
46+
@@ -273,3 +273,46 @@ cbvga_setup(void)
47+
cbvga_setup_modes(addr, bpp, xlines, ylines, linelength);
48+
return 0;
49+
}
50+
+
51+
+#pragma pack(1)
52+
+struct csm_vga_table {
53+
+ u32 signature;
54+
+
55+
+ u32 physical_address;
56+
+ u32 bbp;
57+
+ u32 x_resolution;
58+
+ u32 y_resolution;
59+
+ u32 bytes_per_line;
60+
+};
61+
+#pragma pack()
62+
+
63+
+#define SIGNATURE_16(A, B) ((A) | (B << 8))
64+
+#define SIGNATURE_32(A, B, C, D) (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16))
65+
+
66+
+#define CSM_VGA_TABLE_SIGNATURE SIGNATURE_32 ('C', 'V', 'G', '$')
67+
+
68+
+struct csm_vga_table csm_vga VAR16 __aligned(16) = {
69+
+ .signature = CSM_VGA_TABLE_SIGNATURE,
70+
+};
71+
+
72+
+int
73+
+csmvga_setup(void)
74+
+{
75+
+ dprintf(1, "csm vga init\n");
76+
+
77+
+ if (GET_GLOBAL(HaveRunInit))
78+
+ return 0;
79+
+
80+
+ if (!GET_GLOBAL(csm_vga.physical_address)) {
81+
+ dprintf(1, "No CSM VGA table, exiting\n");
82+
+ return -1;
83+
+ }
84+
+
85+
+ cbvga_setup_modes(GET_GLOBAL(csm_vga.physical_address),
86+
+ GET_GLOBAL(csm_vga.bbp),
87+
+ GET_GLOBAL(csm_vga.x_resolution),
88+
+ GET_GLOBAL(csm_vga.y_resolution),
89+
+ GET_GLOBAL(csm_vga.bytes_per_line));
90+
+
91+
+ return 0;
92+
+}
93+
diff --git a/vgasrc/vgahw.h b/vgasrc/vgahw.h
94+
index a6ddaa95c019..e72fbb49dfe3 100644
95+
--- a/vgasrc/vgahw.h
96+
+++ b/vgasrc/vgahw.h
97+
@@ -57,6 +57,8 @@ static inline int vgahw_setup(void) {
98+
return geodevga_setup();
99+
if (CONFIG_VGA_COREBOOT)
100+
return cbvga_setup();
101+
+ if (CONFIG_VGA_CSM)
102+
+ return csmvga_setup();
103+
if (CONFIG_DISPLAY_BOCHS)
104+
return bochs_display_setup();
105+
if (CONFIG_VGA_RAMFB)
106+
diff --git a/vgasrc/vgautil.h b/vgasrc/vgautil.h
107+
index ea1ac772a270..00ea7821f8bb 100644
108+
--- a/vgasrc/vgautil.h
109+
+++ b/vgasrc/vgautil.h
110+
@@ -20,6 +20,7 @@ int cbvga_save_restore(int cmd, u16 seg, void *data);
111+
int cbvga_set_mode(struct vgamode_s *vmode_g, int flags);
112+
void cbvga_setup_modes(u64 addr, u8 bpp, u32 xlines, u32 ylines, u32 linelength);
113+
int cbvga_setup(void);
114+
+int csmvga_setup(void);
115+
116+
// bochsdisplay.c
117+
int bochs_display_setup(void);
118+
--
119+
2.39.5 (Apple Git-154)
120+

0 commit comments

Comments
 (0)