uefi-rs
uefi-rs copied to clipboard
Implementing pass-through protocols
Right now I'm trying to implement the EFI ATA, NVMe, and SD MMC pass-through protocols. These are defined in SECs. 13.13 (pg. 582), 13.15 (pg. 605), and 13.16 (pg. 615) of UEFI 2.9.
I'm starting off with EFI_ATA_PASS_THRU_PROTOCOL
. I'm currently stuck on the EFI_ATA_PASS_THRU_PROTOCOL.PassThru()
function. Its signature is:
typedef
EFI_STATUS
(EFIAPI *EFI_ATA_PASS_THRU_PASSTHRU) (
IN EFI_ATA_PASS_THRU_PROTOCOL *This,
IN UINT16 Port,
IN UINT16 PortMultiplierPort,
IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet,
IN EFI_EVENT Event OPTIONAL
);
This isn't what I'm stuck on; I'm stuck on the related definitions that this function requires:
typedef struct {
EFI_ATA_STATUS_BLOCK *Asb;
EFI_ATA_COMMAND_BLOCK *Acb;
UINT64 Timeout;
VOID *InDataBuffer;
VOID *OutDataBuffer;
UINT32 InTransferLength;
UINT32 OutTransferLength;
EFI_ATA_PASS_THRU_CMD_PROTOCOL Protocol;
EFI_ATA_PASS_THRU_LENGTH Length;
} EFI_ATA_PASS_THRU_COMMAND_PACKET;
typedef struct _EFI_ATA_COMMAND_BLOCK {
UINT8 Reserved1[2];
UINT8 AtaCommand;
UINT8 AtaFeatures;
UINT8 AtaSectorNumber;
UINT8 AtaCylinderLow;
UINT8 AtaCylinderHigh;
UINT8 AtaDeviceHead;
UINT8 AtaSectorNumberExp;
UINT8 AtaCylinderLowExp;
UINT8 AtaCylinderHighExp;
UINT8 AtaFeaturesExp;
UINT8 AtaSectorCount;
UINT8 AtaSectorCountExp;
UINT8 Reserved2[6];
} EFI_ATA_COMMAND_BLOCK;
typedef struct _EFI_ATA_STATUS_BLOCK {
UINT8 Reserved1[2];
UINT8 AtaStatus;
UINT8 AtaError;
UINT8 AtaSectorNumber;
UINT8 AtaCylinderLow;
UINT8 AtaCylinderHigh;
UINT8 AtaDeviceHead;
UINT8 AtaSectorNumberExp;
UINT8 AtaCylinderLowExp;
UINT8 AtaCylinderHighExp;
UINT8 Reserved2;
UINT8 AtaSectorCount;
UINT8 AtaSectorCountExp;
UINT8 Reserved3[6];
} EFI_ATA_STATUS_BLOCK;
typedef UINT8 EFI_ATA_PASS_THRU_CMD_PROTOCOL;
#define EFI_ATA_PASS_THRU_PROTOCOL_ATA_HARDWARE_RESET 0x00
#define EFI_ATA_PASS_THRU_PROTOCOL_ATA_SOFTWARE_RESET 0x01
#define EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA 0x02
#define EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN 0x04
#define EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT 0x05
#define EFI_ATA_PASS_THRU_PROTOCOL_DMA 0x06
#define EFI_ATA_PASS_THRU_PROTOCOL_DMA_QUEUED 0x07
#define EFI_ATA_PASS_THRU_PROTOCOL_DEVICE_DIAGNOSTIC 0x08
#define EFI_ATA_PASS_THRU_PROTOCOL_DEVICE_RESET 0x09
#define EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN 0x0A
#define EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT 0x0B
#define EFI_ATA_PASS_THRU_PROTOCOL_FPDMA 0x0C
#define EFI_ATA_PASS_THRU_PROTOCOL_RETURN_RESPONSE 0xFF
typedef UINT8 EFI_ATA_PASS_THRU_LENGTH;
#define EFI_ATA_PASS_THRU_LENGTH_BYTES 0x80
#define EFI_ATA_PASS_THRU_LENGTH_MASK 0x70
#define EFI_ATA_PASS_THRU_LENGTH_NO_DATA_TRANSFER 0x00
#define EFI_ATA_PASS_THRU_LENGTH_FEATURES 0x10
#define EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT 0x20
#define EFI_ATA_PASS_THRU_LENGTH_TPSIU 0x30
#define EFI_ATA_PASS_THRU_LENGTH_COUNT 0x0F
Most of these definitions are trivial. What I'm confused about is the void pointers. (This isn't the only EFI protocol that has this, but this is one of them.) What type would I use for this in this environment since I (can't -- I don't think) use c_void?
Hi! Usually, we represent such buffers as *mut u8
, mutable arrays of bytes. If they have any alignment requirements (e.g. the spec says they should be 64-byte aligned), we also add assert
s in the calling code to validate the alignment. See this function for an example.
Hello, any progress on this? I've had NVMe passthrough implemented reasonably well for a while in my uefi project, and I am considering making a PR for this.
Although I am unsure about how to non-manually test it, since it requires passing an ssd to qemu with vfio, or, well, actually running it.
And also I'll need ATA later, so I am asking if I have to do it for myself or is there something you will make a PR with at some point.
@necauqua since the original issue author didn't reply, I'm going to guess they're not actively working on this feature anymore?
Although I am unsure about how to non-manually test it, since it requires passing an ssd to qemu with vfio, or, well, actually running it. Indeed, we'll probably not be able to properly test this protocol in CI. At the most we can statically check the code keeps compiling, but the logic behind it will suffer from some code rot.
That being said, if you've already defined the corresponding protocols and wouldn't mind sharing them with the uefi-rs
crate users, we'd welcome the contribution 😄
Sure, I'd push the ones I have in my project, I need to add docs/missing impls and also yeah most of them are kind of untestable without dedicated hw or smth.
Also ATA passthrough mysteriously does not work for me: at least ATA Identify (just times out) but it's used by PI DiskInfo protocol (which I have also implemented without docs/tests seeking alternatives, as well as StorageSecurityCommand (13.14) and DevicePathToText (10.6.2)) and from it I do get identify data, so it seems like my impl/usage somehow differs from the C ones