Windows kernel extracts various BIOS information at boot-time.
The method it uses to extract SystemBiosDate is very hueristic.
It is done by nt!CmpGetBiosDate().

nt!CmpGetBiosDate() works by scanning all BIOS memory from 0xF0000 to
0xFFFF5 (FSEG) in search for a string which is formatted like a date.
It then chooses the string which represents the most recent date, and
writes it to:

   HKLM/HARDWARE/DESCRIPTION/System SystemBiosDate

This date should usually be BiosDate located at FSEG(0xFFF5).

In some cases when the SMBIOS tables are small enough (both in legacy
and non-legacy mode) - These tables are allocated in FSEG instead of
high-mem, specifically Type0->release_date string which might cause
SystemBiosDate to change - depending on its value. This leads to an
inconsistent behaviour that depends on the SMBIOS table sizes.

We fix this inconsistency by controlling which dates appear in FSEG:

    * Introducing fw_cfg key 'etc/win-bios-date' to control the date
      that appears in FSEG(0xFFF5).
    * If 'etc/win-bios-date' was supplied - we do not allocate the
      SMBIOS tables, which contain dates, in FSEG but in high-mem
      instead.

For reference implementation of nt!CmpGetBiosDate(), see ReactOS:
https://doxygen.reactos.org/d5/dd2/i386_2cmhardwr_8c.html

Reviewed-by: Konrad Rzeszutek Wilk <[email protected]>
Reviewed-by: Arbel Moshe <[email protected]>
Signed-off-by: Sam Eiderman <[email protected]>
Signed-off-by: Liran Alon <[email protected]>
---
 src/boot.c          | 9 +++++++++
 src/fw/biostables.c | 2 +-
 src/fw/smbios.c     | 2 +-
 src/misc.c          | 2 ++
 src/util.h          | 4 ++++
 5 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/src/boot.c b/src/boot.c
index 9f82f3ca..a3e9eb6d 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -285,6 +285,15 @@ boot_init(void)
         }
     }
 
+    int size;
+    char *date = romfile_loadfile("etc/win-bios-date", &size);
+    if (date) {
+        if (size > sizeof(BiosDate) - 1)
+            size = sizeof(BiosDate) - 1;
+        memcpy(BiosDate, date, size);
+        OnlyBiosDateInFSEG = 1;
+    }
+
     BootRetryTime = romfile_loadint("etc/boot-fail-wait", 60*1000);
 
     loadBootOrder();
diff --git a/src/fw/biostables.c b/src/fw/biostables.c
index 269b8582..6e5d4f86 100644
--- a/src/fw/biostables.c
+++ b/src/fw/biostables.c
@@ -448,7 +448,7 @@ smbios_romfile_setup(void)
     }
 
     /* allocate final blob and record its address in the entry point */
-    if (ep.structure_table_length > BUILD_MAX_SMBIOS_FSEG)
+    if (OnlyBiosDateInFSEG || ep.structure_table_length > 
BUILD_MAX_SMBIOS_FSEG)
         tables = malloc_high(ep.structure_table_length);
     else
         tables = malloc_fseg(ep.structure_table_length);
diff --git a/src/fw/smbios.c b/src/fw/smbios.c
index 6f33a329..ab7dc965 100644
--- a/src/fw/smbios.c
+++ b/src/fw/smbios.c
@@ -23,7 +23,7 @@ smbios_entry_point_setup(u16 max_structure_size,
                          u16 number_of_structures)
 {
     void *finaltable;
-    if (structure_table_length <= BUILD_MAX_SMBIOS_FSEG)
+    if (!OnlyBiosDateInFSEG && structure_table_length <= BUILD_MAX_SMBIOS_FSEG)
         // Table is small enough for f-seg - allocate there.  This
         // works around a bug in JunOS (at least for small SMBIOS tables).
         finaltable = malloc_fseg(structure_table_length);
diff --git a/src/misc.c b/src/misc.c
index b5117304..a31800d7 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -176,6 +176,8 @@ struct descloc_s rombios32_gdt_48 VARFSEG = {
 // BIOS build date
 char BiosDate[] VARFSEGFIXED(0xfff5) = "06/23/99";
 
+u8 OnlyBiosDateInFSEG = 0;
+
 u8 BiosModelId VARFSEGFIXED(0xfffe) = BUILD_MODEL_ID;
 
 u8 BiosChecksum VARFSEGFIXED(0xffff);
diff --git a/src/util.h b/src/util.h
index 6dd080f6..e7eab27c 100644
--- a/src/util.h
+++ b/src/util.h
@@ -243,6 +243,10 @@ void lpt_setup(void);
 // version.c
 extern const char VERSION[], BUILDINFO[];
 
+// misc.c
+extern char BiosDate[sizeof("dd/mm/yy")] __aligned(1);
+extern u8 OnlyBiosDateInFSEG;
+
 // vgahooks.c
 void handle_155f(struct bregs *regs);
 void handle_157f(struct bregs *regs);
-- 
2.13.3
_______________________________________________
SeaBIOS mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to