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");