Page 1 of 1

UEFI - Disks detections and write data

Posted: Mon Dec 14, 2020 5:13 pm
by Fulgurance
Hello, I have question, actually I make my library for use UEFI calls, but now, I want to detect all disks connected and read and write. But I don't found this type of fonction into the UEFI documentation. I missed something ?

Re: UEFI - Disks detections and write data

Posted: Mon Dec 14, 2020 5:32 pm
by zaval
yes, you did. read the chapter "Protocols - Media Access", namely EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, EFI_FILE_PROTOCOL - for reading/writing FAT volumes, DISK IO, BLOCK IO protocols for raw access to storage devices in case of other file systems (whose logic you should implement by yourself, of course).

Re: UEFI - Disks detections and write data

Posted: Tue Dec 15, 2020 2:10 am
by Fulgurance
Okay, you confirmed what I was thinking.

But I see many times I need to specify media ID, but before, I want to know all internal and external storage connected, how I can do that?

Re: UEFI - Disks detections and write data

Posted: Tue Dec 15, 2020 9:49 am
by bzt
Fulgurance wrote:But I see many times I need to specify media ID, but before, I want to know all internal and external storage connected, how I can do that?
For that EFI_SIMPLE_FILE_SYSTEM_PROTOCOL is no good, because that can only be used for file systems that have a driver (typically FAT-only). To iterate on all disks, you'll need the BLOCK_IO_PROTOCOL. Sadly our wiki only has an Assembly example (fasm dialect) and no C tutorial, but here's how I do it from C in my loader.

Basically you locate the BLOCK_IO_PROTOCOL, then you allocate a buffer for its handle list. Then you query the list and iterate on the handles in it (line 1697 in my loader). Within the iteration using the current handle you can get an interface for each and every block device in the system. That interface has the MediaID field. Then you can use bio->ReadBlocks and bio->WriteBlocks to access the device at sector level. For example my loader reads the GPT on each device and parses that itself to detect partitions that are otherwise unhandled by the UEFI. Hope this helps.

For completeness, there's also a DISK_IO_PROTOCOL, but I had hard time finding a firmware that support it. BLOCK_IO_PROTOCOL on the other hand looks like is always available.

Cheers,
bzt

EDIT: I've created a wiki page for reading blocks under UEFI. It's a first draft, feel free to expand it.

Re: UEFI - Disks detections and write data

Posted: Tue Dec 15, 2020 11:06 am
by Fulgurance
Sadly? No good things for me, because I just use fasm! Thanks for your reply, I will ask you if I have any question

Re: UEFI - Disks detections and write data

Posted: Wed Dec 16, 2020 7:26 am
by Fulgurance
Okay, I have just one question, because I'm French, I don't understand one word in all uefi documentation :

HANDLE : what is an handle? Because I seen you use LocateHandle function, and if I understand, when you perform that, you looking for what devices is attached with this protocol, its that? And when you locate the handle, the pointer have address of an array?

And how you know that? Because block io is a protocol? How you know you can look for devices attached with LocateHandle?

Re: UEFI - Disks detections and write data

Posted: Wed Dec 16, 2020 8:35 am
by bzt
Fulgurance wrote:Okay, I have just one question, because I'm French, I don't understand one word in all uefi documentation :

HANDLE : what is an handle? Because I seen you use LocateHandle function, and if I understand, when you perform that, you looking for what devices is attached with this protocol, its that? And when you locate the handle, the pointer have address of an array?
Okay, handle is just an abstraction. Here it refers to block devices, but for example the FILE* pointer in C is also called a handle in Windows parlance. Handle can be anything that refers to an object of any kind. It is usually a pointer, but could be a numeric ID as well, that's not specified, only the fact that it's unique to an object.

LocateHandle - receives a buffer address as input and it returns an array with handles in that buffer, one for each block device if you call it with BLOCK_IO_PROTOCOL (think of it as a list of IDs).
HandleProtocol - receives a handle as input and returns a pointer to a struct with properties and methods (think of it as retrieving an OOP object for a specific ID).
Fulgurance wrote:How you know you can look for devices attached with LocateHandle?
In general, LocateHandle returns a list of object references (using handles) that implement the specified protocol. Then HandleProtocol is used to retrieve an object instance pointer for a handle, because handle is not necessarily a pointer (it's an abstract ID). What properties and methods those objects have depends on the protocol you've queried the handles for. Hope this makes sense to you. In this example, BLOCK_IO_PROTOCOL is queried, and then the returned objects are casted to EFI_BLOCK_IO struct, because that's the struct that describes the properties and methods of the BLOCK_IO_PROTOCL protocol. So there's a one-to-one relation between protocols (which are GUIDs) and interfaces (which are structs).

Cheers,
bzt