Add more linker protections around variables accessed from 16bit mode.
Rename VAR16 to VAR16_32 -- that macro supports accesses from both
16bit and 32bit mode.
Introduce a new macro VAR16 that must be present on all global
variables accessed from 16bit mode.
diff --git a/Makefile b/Makefile
index 24c67c2..3a24433 100644
--- a/Makefile
+++ b/Makefile
@@ -76,7 +76,7 @@
$(OUT)%.proc.16.s: $(OUT)%.16.s
@echo " Moving data sections to text in $@"
- $(Q)sed 's/\t\.section\t\.rodata.*// ; s/\t\.data//' < $< > $@
+ $(Q)sed 's/^\t\.section\t\.\(ro\)\?data.*// ; s/^\t\.data$$//' < $< > $@
$(OUT)%.16.s: %.c
@echo " Compiling to assembler $@"
diff --git a/src/ata.c b/src/ata.c
index c198264..7e31002 100644
--- a/src/ata.c
+++ b/src/ata.c
@@ -29,7 +29,7 @@
#define IDE_TIMEOUT 32000u //32 seconds max for IDE ops
-struct ata_s ATA VAR16;
+struct ata_s ATA VAR16_32;
/****************************************************************
diff --git a/src/cbt.c b/src/cbt.c
index 8a2a11a..5554fda 100644
--- a/src/cbt.c
+++ b/src/cbt.c
@@ -27,7 +27,7 @@
// INT 16/AH=09h (keyboard functionality) supported
#define CBT_F2_INT1609 (1<<6)
-struct bios_config_table_s BIOS_CONFIG_TABLE __aligned(1) = {
+struct bios_config_table_s BIOS_CONFIG_TABLE __aligned(1) VAR16 = {
.size = sizeof(BIOS_CONFIG_TABLE) - 2,
.model = CONFIG_MODEL_ID,
.submodel = CONFIG_SUBMODEL_ID,
diff --git a/src/cdrom.c b/src/cdrom.c
index f955f18..7ce7da7 100644
--- a/src/cdrom.c
+++ b/src/cdrom.c
@@ -11,7 +11,7 @@
#include "bregs.h" // struct bregs
#include "biosvar.h" // GET_EBDA
-struct cdemu_s CDEMU VAR16;
+struct cdemu_s CDEMU VAR16_32;
/****************************************************************
diff --git a/src/clock.c b/src/clock.c
index 4590adc..c76ea75 100644
--- a/src/clock.c
+++ b/src/clock.c
@@ -51,7 +51,7 @@
#define PIT_TICK_RATE 1193182 // Underlying HZ of PIT
#define CALIBRATE_COUNT 0x800 // Approx 1.7ms
-u32 cpu_khz VAR16;
+u32 cpu_khz VAR16_32;
static void
calibrate_tsc()
diff --git a/src/floppy.c b/src/floppy.c
index 6354bd8..da812ba 100644
--- a/src/floppy.c
+++ b/src/floppy.c
@@ -20,7 +20,7 @@
// Since no provisions are made for multiple drive types, most
// values in this table are ignored. I set parameters for 1.44M
// floppy here
-struct floppy_ext_dbt_s diskette_param_table2 VAR16 = {
+struct floppy_ext_dbt_s diskette_param_table2 VAR16_32 = {
.dbt = {
.specify1 = 0xAF,
.specify2 = 0x02, // head load time 0000001, DMA used
diff --git a/src/floppy_dbt.c b/src/floppy_dbt.c
index c391d9e..2a686dc 100644
--- a/src/floppy_dbt.c
+++ b/src/floppy_dbt.c
@@ -4,7 +4,7 @@
//
// This file may be distributed under the terms of the GNU GPLv3 license.
-#include "disk.h" // diskette_param_table
+#include "disk.h" // struct floppy_dbt_s
// Since no provisions are made for multiple drive types, most
// values in this table are ignored. I set parameters for 1.44M
diff --git a/src/font.c b/src/font.c
index 17f0690..99c7f43 100644
--- a/src/font.c
+++ b/src/font.c
@@ -7,7 +7,7 @@
* found at ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
* This font is public domain
*/
-const u8 vgafont8[128*8] __aligned(1) = {
+const u8 vgafont8[128*8] __aligned(1) VAR16 = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e,
0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e,
diff --git a/src/kbd.c b/src/kbd.c
index 702a032..9c59005 100644
--- a/src/kbd.c
+++ b/src/kbd.c
@@ -148,17 +148,17 @@
ascii_code = 0;
regs->ax = (scan_code << 8) | ascii_code;
- if (incr) {
- u16 buffer_start = GET_BDA(kbd_buf_start_offset);
- u16 buffer_end = GET_BDA(kbd_buf_end_offset);
-
- buffer_head += 2;
- if (buffer_head >= buffer_end)
- buffer_head = buffer_start;
- SET_BDA(kbd_buf_head, buffer_head);
- } else {
+ if (!incr) {
regs->flags &= ~F_ZF;
+ return;
}
+ u16 buffer_start = GET_BDA(kbd_buf_start_offset);
+ u16 buffer_end = GET_BDA(kbd_buf_end_offset);
+
+ buffer_head += 2;
+ if (buffer_head >= buffer_end)
+ buffer_head = buffer_start;
+ SET_BDA(kbd_buf_head, buffer_head);
}
// read keyboard input
@@ -326,7 +326,7 @@
u16 control;
u16 alt;
u8 lock_flags;
-} scan_to_scanascii[MAX_SCAN_CODE + 1] = {
+} scan_to_scanascii[MAX_SCAN_CODE + 1] VAR16 = {
{ none, none, none, none, none },
{ 0x011b, 0x011b, 0x011b, 0x0100, none }, /* escape */
{ 0x0231, 0x0221, none, 0x7800, none }, /* 1! */
diff --git a/src/pirtable.c b/src/pirtable.c
index f776ee9..ba141a5 100644
--- a/src/pirtable.c
+++ b/src/pirtable.c
@@ -9,7 +9,7 @@
#include "util.h" // checksum
#include "biosvar.h" // SET_EBDA
-u16 PirOffset VAR16;
+u16 PirOffset VAR16_32;
struct pir_table {
struct pir_header pir;
@@ -18,7 +18,7 @@
extern struct pir_table PIR_TABLE;
#if CONFIG_PIRTABLE && !CONFIG_COREBOOT
-struct pir_table PIR_TABLE __aligned(16) VAR16 = {
+struct pir_table PIR_TABLE __aligned(16) VAR16_32 = {
.pir = {
.version = 0x0100,
.size = sizeof(struct pir_table),
diff --git a/src/pnpbios.c b/src/pnpbios.c
index 21d140a..8bf71dc 100644
--- a/src/pnpbios.c
+++ b/src/pnpbios.c
@@ -28,7 +28,7 @@
extern const char pnp_string[];
#if CONFIG_PNPBIOS
-struct pnpheader PNPHEADER __aligned(16) VAR16 = {
+struct pnpheader PNPHEADER __aligned(16) VAR16_32 = {
.signature = PNP_SIGNATURE,
.version = 0x10,
.length = sizeof(PNPHEADER),
@@ -41,7 +41,7 @@
// We need a copy of this string in the 0xf000 segment, but we are not
// actually a PnP BIOS, so make sure it is *not* aligned, so OSes will
// not see it if they scan.
-const char pnp_string[] __aligned(2) VAR16 = " $PnP";
+const char pnp_string[] __aligned(2) VAR16_32 = " $PnP";
#endif
#define FUNCTION_NOT_SUPPORTED 0x82
diff --git a/src/rombios16.lds.S b/src/rombios16.lds.S
index 009eb89..2966ce6 100644
--- a/src/rombios16.lds.S
+++ b/src/rombios16.lds.S
@@ -16,10 +16,7 @@
*(.text)
code16_rodata = . ;
*(.rodata*)
- *(.data)
- code16_bss = . ;
- *(.bss)
- *(COMMON)
+ *(.data.var16)
}
freespace1_start = . ;
code16_end = . ;
@@ -31,4 +28,8 @@
*(.text.fixed.addr)
}
code16_fixed_end = . ;
+
+ // Discard regular data sections to force a link error if
+ // 16bit code attempts to access data not marked with VAR16.
+ /DISCARD/ : { *(.data) *(.bss) *(COMMON) }
}
diff --git a/src/smpdetect.c b/src/smpdetect.c
index 202a82a..b334649 100644
--- a/src/smpdetect.c
+++ b/src/smpdetect.c
@@ -46,7 +46,7 @@
return *(volatile const u8 *)addr;
}
-u32 smp_cpus VAR16;
+u32 smp_cpus VAR16_32;
extern void smp_ap_boot_code();
ASM16(
" .global smp_ap_boot_code\n"
diff --git a/src/system.c b/src/system.c
index abbfbbf..7a0d20c 100644
--- a/src/system.c
+++ b/src/system.c
@@ -267,12 +267,12 @@
}
// Info on e820 map location and size.
-struct e820entry *e820_list VAR16;
-int e820_count VAR16;
+struct e820entry *e820_list VAR16_32;
+int e820_count VAR16_32;
// Amount of continuous ram under 4Gig
-u32 RamSize VAR16;
+u32 RamSize VAR16_32;
// Amount of continuous ram >4Gig
-u64 RamSizeOver4G VAR16;
+u64 RamSizeOver4G;
static void
handle_15e820(struct bregs *regs)
diff --git a/src/types.h b/src/types.h
index f7a0e9a..587cb41 100644
--- a/src/types.h
+++ b/src/types.h
@@ -28,14 +28,17 @@
# define VISIBLE16 __VISIBLE
// Notes a function as externally visible in the 32bit code chunk.
# define VISIBLE32
+// Designate a variable as (only) visible to 16bit code.
+# define VAR16 __attribute__((section(".data.var16")))
// Designate a variable as visible to both 32bit and 16bit code.
-# define VAR16 __VISIBLE
+# define VAR16_32 VAR16 __VISIBLE
// Designate top-level assembler as 16bit only.
# define ASM16(code) asm(code)
#else
# define VISIBLE16
# define VISIBLE32 __VISIBLE
-# define VAR16 __VISIBLE __attribute__((section(".discard.var16"))) __attribute__((weak))
+# define VAR16 __attribute__((section(".discard.var16")))
+# define VAR16_32 VAR16 __VISIBLE __attribute__((weak))
# define ASM16(code)
#endif
diff --git a/src/vgahooks.c b/src/vgahooks.c
index 8f55c49..7cacbdf 100644
--- a/src/vgahooks.c
+++ b/src/vgahooks.c
@@ -46,7 +46,7 @@
if (!(reg & 0x80))
goto err;
- static u8 mem_power[] = {0, 3, 4, 5, 6, 7, 8, 9};
+ static u8 mem_power[] VAR16 = {0, 3, 4, 5, 6, 7, 8, 9};
return GET_GLOBAL(mem_power[(reg >> 4) & 0x7]);
err:
dprintf(1, "Warning: VGA memory size is hardcoded\n");