bios: make the BIOS writable

This will be used for live patching of the VESA BIOS.

Change-Id: I66c2dfd950262b5ba4d1e7b424eac46f0695297a
Reviewed-on: https://review.haiku-os.org/c/haiku/+/4621
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Adrien Destugues
2021-10-20 17:17:18 +00:00
committed by waddlesplash
parent 411ccfeb96
commit ed7b6396e3
+27 -19
View File
@@ -21,37 +21,45 @@ struct BIOSState {
BIOSState() BIOSState()
: :
mapped_address(0), mapped_address(0),
bios_area(-1), area(-1),
ram_area(-1),
allocated_size(0) allocated_size(0)
{ {
} }
~BIOSState() ~BIOSState()
{ {
if (bios_area >= 0) if (area >= 0)
delete_area(bios_area); delete_area(area);
if (ram_area >= 0)
delete_area(ram_area);
} }
addr_t mapped_address; addr_t mapped_address;
area_id bios_area; area_id area;
area_id ram_area;
size_t allocated_size; size_t allocated_size;
}; };
// BIOS memory layout definitions. // BIOS memory layout definitions.
// Bottom of RAM contains the interrupt jump vectors
// They need to be copied to our memory area
static const uint32 kBDABase = 0; static const uint32 kBDABase = 0;
static const uint32 kBDASize = 0x1000; static const uint32 kBDASize = 0x1000;
static const uint32 kEBDABase = 0x90000;
static const uint32 kEBDASize = 0x70000; // Remaining part of RAM (left uninitialized initially)
static const uint32 kRAMBase = 0x1000; static const uint32 kRAMBase = 0x1000;
static const uint32 kRAMSize = 0x8f000; static const uint32 kRAMSize = 0x8f000;
static const uint32 kStackSize = 0x1000;
// Upper part of address space: a bit of RAM, the video RAM, then the ROMs
// Copied to the memory area as well, so the BIOS can be patched if needed.
static const uint32 kEBDABase = 0x90000;
static const uint32 kEBDASize = 0x70000;
// Total size of the above
static const uint32 kTotalSize = 0x100000; static const uint32 kTotalSize = 0x100000;
// The stack is dynamically allocated somewhere inside the RAM
static const uint32 kStackSize = 0x1000;
static sem_id sBIOSLock; static sem_id sBIOSLock;
static BIOSState* sCurrentBIOSState; static BIOSState* sCurrentBIOSState;
@@ -218,13 +226,13 @@ bios_prepare(bios_state** _state)
return status; return status;
// Map RAM for for the BIOS. // Map RAM for for the BIOS.
state->ram_area = create_area("bios ram", (void**)&state->mapped_address, state->area = create_area("bios", (void**)&state->mapped_address,
B_EXACT_ADDRESS, kBDASize + kRAMSize, B_NO_LOCK, B_KERNEL_READ_AREA B_EXACT_ADDRESS, kTotalSize, B_NO_LOCK, B_KERNEL_READ_AREA
| B_KERNEL_WRITE_AREA); | B_KERNEL_WRITE_AREA);
if (state->ram_area < B_OK) { if (state->area < B_OK) {
vm_unreserve_address_range(VMAddressSpace::KernelID(), vm_unreserve_address_range(VMAddressSpace::KernelID(),
(void*)state->mapped_address, kTotalSize); (void*)state->mapped_address, kTotalSize);
return state->ram_area; return state->area;
} }
// Copy the interrupt vectors and the BIOS data area. // Copy the interrupt vectors and the BIOS data area.
@@ -238,12 +246,12 @@ bios_prepare(bios_state** _state)
// Map the extended BIOS data area and VGA memory. // Map the extended BIOS data area and VGA memory.
void* address = (void*)(state->mapped_address + kEBDABase); void* address = (void*)(state->mapped_address + kEBDABase);
state->bios_area = map_physical_memory("bios", kEBDABase, kEBDASize, status = vm_memcpy_from_physical(address, kEBDABase, kEBDASize, false);
B_EXACT_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, &address);
if (state->bios_area < B_OK) { if (status != B_OK) {
vm_unreserve_address_range(VMAddressSpace::KernelID(), vm_unreserve_address_range(VMAddressSpace::KernelID(),
(void*)state->mapped_address, kTotalSize); (void*)state->mapped_address, kTotalSize);
return state->bios_area; return status;
} }
// Attempt to acquire exclusive access to the BIOS. // Attempt to acquire exclusive access to the BIOS.