Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 0 additions & 26 deletions src/csmwrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,27 +45,6 @@ static void *find_table(uint32_t signature, uint8_t *csm_bin_base, size_t size)
return Table;
}

int test_bios_region_rw()
{
uint32_t backup;
uint32_t *bios_region = (uint32_t *)BIOSROM_START;
uint32_t *bios_region_end = (uint32_t *)BIOSROM_END;
uint32_t *ptr = bios_region;

while (ptr < bios_region_end) {
backup = *ptr;
*ptr = 0xdeadbeef;
if (*ptr != 0xdeadbeef) {
printf("Unable to write to BIOS region\n");
return -1;
}
*ptr = backup;
ptr++;
}

return 0;
}

int set_smbios_table()
{
UINTN i;
Expand Down Expand Up @@ -134,11 +113,6 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
}
printf("Unlock!\n");

if (test_bios_region_rw()) {
printf("BIOS region bad\n");
return -1;
}

apply_intel_platform_workarounds();

csm_bin_base = (uintptr_t)BIOSROM_END - sizeof(Csm16_bin);
Expand Down
4 changes: 4 additions & 0 deletions src/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

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

static inline void clflush(void *addr) {
asm volatile ("clflush (%0)" :: "r"(addr) : "memory");
}

static inline void writel(void *addr, uint32_t val) {
barrier();
*(volatile uint32_t *)addr = val;
Expand Down
34 changes: 32 additions & 2 deletions src/unlock_region.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* with fallback to direct PCI configuration space access for specific chipsets.
*/

#include <stdbool.h>
#include <efi.h>
#include "csmwrap.h"
#include "edk2/LegacyRegion2.h"
Expand Down Expand Up @@ -298,6 +299,30 @@ EFI_STATUS print_legacy_region_info(EFI_LEGACY_REGION2_PROTOCOL *legacy_region)
return EFI_SUCCESS;
}

static bool test_bios_region_rw(void) {
uint32_t *bios_region = (uint32_t *)BIOSROM_START;
uint32_t *bios_region_end = (uint32_t *)BIOSROM_END;
uint32_t *ptr = bios_region;

while (ptr < bios_region_end) {
clflush(ptr);
uint32_t val = readl(ptr);

writel(ptr, ~val);
clflush(ptr);

if (readl(ptr) != ~val) {
printf("Unable to write to BIOS region\n");
return false;
}

writel(ptr, val);
ptr++;
}

return true;
}

/**
* Main function to unlock the BIOS region
* Tries to use the UEFI protocol first, then falls back to chipset-specific methods
Expand All @@ -309,6 +334,11 @@ int unlock_bios_region(void)
EFI_LEGACY_REGION2_PROTOCOL *legacy_region = NULL;
EFI_STATUS status;

// No need to do anything if the region is already unlocked and working.
if (test_bios_region_rw()) {
return 0;
}

/* First, try to use the Legacy Region 2 Protocol */
status = gBS->LocateProtocol(
&gEfiLegacyRegion2ProtocolGuid,
Expand All @@ -322,7 +352,7 @@ int unlock_bios_region(void)

/* Try to unlock using the protocol */
status = unlock_legacy_region_protocol();
if (!EFI_ERROR(status)) {
if (!EFI_ERROR(status) && test_bios_region_rw()) {
return 0; /* Success */
}

Expand Down Expand Up @@ -367,5 +397,5 @@ int unlock_bios_region(void)
break;
}

return status == 0 ? 0 : -1;
return (status == 0 && test_bios_region_rw()) ? 0 : -1;
}