Skip to content

Commit ae6c927

Browse files
committed
Improve test_bios_region_rw() by using clflush for properly ensuring caches are flushed
Also, move test_bios_region_rw() to unlock_region.c file and make it static.
1 parent 16a4627 commit ae6c927

File tree

3 files changed

+38
-28
lines changed

3 files changed

+38
-28
lines changed

src/csmwrap.c

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -45,27 +45,6 @@ static void *find_table(uint32_t signature, uint8_t *csm_bin_base, size_t size)
4545
return Table;
4646
}
4747

48-
int test_bios_region_rw()
49-
{
50-
uint32_t backup;
51-
uint32_t *bios_region = (uint32_t *)BIOSROM_START;
52-
uint32_t *bios_region_end = (uint32_t *)BIOSROM_END;
53-
uint32_t *ptr = bios_region;
54-
55-
while (ptr < bios_region_end) {
56-
backup = *ptr;
57-
*ptr = 0xdeadbeef;
58-
if (*ptr != 0xdeadbeef) {
59-
printf("Unable to write to BIOS region\n");
60-
return -1;
61-
}
62-
*ptr = backup;
63-
ptr++;
64-
}
65-
66-
return 0;
67-
}
68-
6948
int set_smbios_table()
7049
{
7150
UINTN i;
@@ -134,11 +113,6 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
134113
}
135114
printf("Unlock!\n");
136115

137-
if (test_bios_region_rw()) {
138-
printf("BIOS region bad\n");
139-
return -1;
140-
}
141-
142116
apply_intel_platform_workarounds();
143117

144118
csm_bin_base = (uintptr_t)BIOSROM_END - sizeof(Csm16_bin);

src/io.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
#define barrier() __asm__ __volatile__("": : :"memory")
88

9+
static inline void clflush(void *addr) {
10+
asm volatile ("clflush (%0)" :: "r"(addr) : "memory");
11+
}
12+
913
static inline void writel(void *addr, uint32_t val) {
1014
barrier();
1115
*(volatile uint32_t *)addr = val;

src/unlock_region.c

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* with fallback to direct PCI configuration space access for specific chipsets.
66
*/
77

8+
#include <stdbool.h>
89
#include <efi.h>
910
#include "csmwrap.h"
1011
#include "edk2/LegacyRegion2.h"
@@ -298,6 +299,32 @@ EFI_STATUS print_legacy_region_info(EFI_LEGACY_REGION2_PROTOCOL *legacy_region)
298299
return EFI_SUCCESS;
299300
}
300301

302+
static bool test_bios_region_rw(void) {
303+
uint32_t *bios_region = (uint32_t *)BIOSROM_START;
304+
uint32_t *bios_region_end = (uint32_t *)BIOSROM_END;
305+
uint32_t *ptr = bios_region;
306+
307+
while (ptr < bios_region_end) {
308+
uint32_t val;
309+
310+
clflush(ptr);
311+
val = readl(ptr);
312+
313+
writel(ptr, ~val);
314+
clflush(ptr);
315+
316+
if (readl(ptr) != ~val) {
317+
printf("Unable to write to BIOS region\n");
318+
return false;
319+
}
320+
321+
writel(ptr, val);
322+
ptr++;
323+
}
324+
325+
return true;
326+
}
327+
301328
/**
302329
* Main function to unlock the BIOS region
303330
* Tries to use the UEFI protocol first, then falls back to chipset-specific methods
@@ -309,6 +336,11 @@ int unlock_bios_region(void)
309336
EFI_LEGACY_REGION2_PROTOCOL *legacy_region = NULL;
310337
EFI_STATUS status;
311338

339+
// No need to do anything if the region is already unlocked and working.
340+
if (test_bios_region_rw()) {
341+
return 0;
342+
}
343+
312344
/* First, try to use the Legacy Region 2 Protocol */
313345
status = gBS->LocateProtocol(
314346
&gEfiLegacyRegion2ProtocolGuid,
@@ -322,7 +354,7 @@ int unlock_bios_region(void)
322354

323355
/* Try to unlock using the protocol */
324356
status = unlock_legacy_region_protocol();
325-
if (!EFI_ERROR(status)) {
357+
if (!EFI_ERROR(status) && test_bios_region_rw()) {
326358
return 0; /* Success */
327359
}
328360

@@ -367,5 +399,5 @@ int unlock_bios_region(void)
367399
break;
368400
}
369401

370-
return status == 0 ? 0 : -1;
402+
return (status == 0 && test_bios_region_rw()) ? 0 : -1;
371403
}

0 commit comments

Comments
 (0)