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]