Reading sectors under UEFI: Difference between revisions

From OSDev.wiki
Jump to navigation Jump to search
[unchecked revision][unchecked revision]
Content added Content deleted
m (Bot: Replace deprecated source tag with syntaxhighlight)
m (Bot: Replace deprecated source tag with syntaxhighlight)
 
Line 28: Line 28:


We should iterate on that array, and use ith handle to get the block IO interface for a device.
We should iterate on that array, and use ith handle to get the block IO interface for a device.
<source lang="c">
<syntaxhighlight lang="c">
for (i = 0; i < handle_size / sizeof(EFI_HANDLE); i++) {
for (i = 0; i < handle_size / sizeof(EFI_HANDLE); i++) {
status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i], &bioGuid, (void **) &bio);
status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i], &bioGuid, (void **) &bio);
Line 36: Line 36:
/* TODO: do something with that device. */
/* TODO: do something with that device. */
}
}
</syntaxhighlight>
</source>


== Loading Raw Sectors ==
== Loading Raw Sectors ==

Latest revision as of 05:43, 9 June 2024

Note that you don't necessarily need to access raw block devices, because UEFI provides files abstraction with EFI_SIMPLE_FILE_SYSTEM_PROTOCOL (typically limited to FAT-only partitions).

Iterating on Disks

If you already have a handle for a block device, then your job is easy. However more often you don't, which means first you must query the list of block devices in the system. Because you don't know in advance how many devices there are, you must locate the BLOCK_IO_PROTOCOL twice.

EFI_GUID bioGuid = BLOCK_IO_PROTOCOL;
EFI_BLOCK_IO *bio;
EFI_HANDLE *handles = NULL;
UINTN handle_size = 0;

/* first, locate the protocol with empty buffer */
status = uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &bioGuid, NULL, &handle_size, handles);
if (status != EFI_BUFFER_TOO_SMALL || handle_size == 0) {
    /* AUCH, error we don't have BLOCK_IO */
}

/* get a buffer for the handles now that we know the buffer size */
status = uefi_call_wrapper(BS->AllocatePages, 4, 0, 2, (handle_size + PAGESIZE-1) / PAGESIZE, (EFI_PHYSICAL_ADDRESS*)&handles);
if (EFI_ERROR(status) || handles == NULL) {
    /* AUCH, error memory allocation failed */
}

/* second round, locate the protocol with big enough buffer */
status = uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &bioGuid, NULL, &handle_size, handles);

Now "handles" is an array that has a handle for each and every block device in the system.

We should iterate on that array, and use ith handle to get the block IO interface for a device.

for (i = 0; i < handle_size / sizeof(EFI_HANDLE); i++) {
    status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i], &bioGuid, (void **) &bio);
    /* if unsuccessful, skip and go over to the next device */
    if (EFI_ERROR(status) || bio == NULL || bio->Media->BlockSize==0)
        continue;
    /* TODO: do something with that device. */
}

Loading Raw Sectors

The "bio" interface inside the iteration above refers to one particular device. You can use that interface to load sectors from that device quite easily:

UINT8 mbr[512];

status = uefi_call_wrapper(bio->ReadBlocks, 5, bio, bio->Media->MediaId, 1, 512, &mbr);
if (EFI_ERROR(status)) {
    /* AUCH, error reading sector */
}

See also

Articles

External Links