Ring3: Added Ring3BlockIo and Ring3DiskIo drafts.

This commit is contained in:
Mikhail Krichanov 2024-02-19 11:35:25 +03:00
parent 3868edbf44
commit f82b04a2dc
5 changed files with 317 additions and 18 deletions

View File

@ -25,6 +25,7 @@
Ring3.h
DxeRing3.c
Ring3UefiBootServices.c
Ring3Protocols.c
[Sources.X64]
X64/SysCall.nasm

View File

@ -5,6 +5,14 @@
**/
#include <Protocol/BlockIo.h>
#include <Protocol/DevicePathUtilities.h>
#include <Protocol/DiskIo.h>
#include <Protocol/LoadedImage.h>
extern EFI_BLOCK_IO_PROTOCOL mCoreBlockIo;
extern EFI_DISK_IO_PROTOCOL mCoreDiskIo;
EFI_STATUS
EFIAPI
SysCall (
@ -1011,3 +1019,151 @@ Ring3CreateEventEx (
IN CONST EFI_GUID *EventGroup OPTIONAL,
OUT EFI_EVENT *Event
);
/**
Reset the Block Device.
@param This Indicates a pointer to the calling context.
@param ExtendedVerification Driver may perform diagnostics on reset.
@retval EFI_SUCCESS The device was reset.
@retval EFI_DEVICE_ERROR The device is not functioning properly and could
not be reset.
**/
EFI_STATUS
EFIAPI
Ring3BlockIoReset (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
);
/**
Read BufferSize bytes from Lba into Buffer.
@param This Indicates a pointer to the calling context.
@param MediaId Id of the media, changes every time the media is replaced.
@param Lba The starting Logical Block Address to read from
@param BufferSize Size of Buffer, must be a multiple of device block size.
@param Buffer A pointer to the destination buffer for the data. The caller is
responsible for either having implicit or explicit ownership of the buffer.
@retval EFI_SUCCESS The data was read correctly from the device.
@retval EFI_DEVICE_ERROR The device reported an error while performing the read.
@retval EFI_NO_MEDIA There is no media in the device.
@retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
or the buffer is not on proper alignment.
**/
EFI_STATUS
EFIAPI
Ring3BlockIoRead (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
OUT VOID *Buffer
);
/**
Write BufferSize bytes from Lba into Buffer.
@param This Indicates a pointer to the calling context.
@param MediaId The media ID that the write request is for.
@param Lba The starting logical block address to be written. The caller is
responsible for writing to only legitimate locations.
@param BufferSize Size of Buffer, must be a multiple of device block size.
@param Buffer A pointer to the source buffer for the data.
@retval EFI_SUCCESS The data was written correctly to the device.
@retval EFI_WRITE_PROTECTED The device can not be written to.
@retval EFI_DEVICE_ERROR The device reported an error while performing the write.
@retval EFI_NO_MEDIA There is no media in the device.
@retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
@retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
or the buffer is not on proper alignment.
**/
EFI_STATUS
EFIAPI
Ring3BlockIoWrite (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
IN VOID *Buffer
);
/**
Flush the Block Device.
@param This Indicates a pointer to the calling context.
@retval EFI_SUCCESS All outstanding data was written to the device
@retval EFI_DEVICE_ERROR The device reported an error while writting back the data
@retval EFI_NO_MEDIA There is no media in the device.
**/
EFI_STATUS
EFIAPI
Ring3BlockIoFlush (
IN EFI_BLOCK_IO_PROTOCOL *This
);
/**
Read BufferSize bytes from Offset into Buffer.
@param This Protocol instance pointer.
@param MediaId Id of the media, changes every time the media is replaced.
@param Offset The starting byte offset to read from
@param BufferSize Size of Buffer
@param Buffer Buffer containing read data
@retval EFI_SUCCESS The data was read correctly from the device.
@retval EFI_DEVICE_ERROR The device reported an error while performing the read.
@retval EFI_NO_MEDIA There is no media in the device.
@retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
@retval EFI_INVALID_PARAMETER The read request contains device addresses that are not
valid for the device.
**/
EFI_STATUS
EFIAPI
Ring3DiskIoRead (
IN EFI_DISK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN UINT64 Offset,
IN UINTN BufferSize,
OUT VOID *Buffer
);
/**
Writes a specified number of bytes to a device.
@param This Indicates a pointer to the calling context.
@param MediaId ID of the medium to be written.
@param Offset The starting byte offset on the logical block I/O device to write.
@param BufferSize The size in bytes of Buffer. The number of bytes to write to the device.
@param Buffer A pointer to the buffer containing the data to be written.
@retval EFI_SUCCESS The data was written correctly to the device.
@retval EFI_WRITE_PROTECTED The device can not be written to.
@retval EFI_DEVICE_ERROR The device reported an error while performing the write.
@retval EFI_NO_MEDIA There is no media in the device.
@retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
@retval EFI_INVALID_PARAMETER The write request contains device addresses that are not
valid for the device.
**/
EFI_STATUS
EFIAPI
Ring3DiskIoWrite (
IN EFI_DISK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN UINT64 Offset,
IN UINTN BufferSize,
IN VOID *Buffer
);

View File

@ -0,0 +1,82 @@
/** @file
Copyright (c) 2024, Mikhail Krichanov. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
**/
#include "Ring3.h"
EFI_BLOCK_IO_PROTOCOL mCoreBlockIo;
EFI_DISK_IO_PROTOCOL mCoreDiskIo;
EFI_STATUS
EFIAPI
Ring3BlockIoReset (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
)
{
return EFI_UNSUPPORTED;
}
EFI_STATUS
EFIAPI
Ring3BlockIoRead (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
OUT VOID *Buffer
)
{
return EFI_UNSUPPORTED;
}
EFI_STATUS
EFIAPI
Ring3BlockIoWrite (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
IN VOID *Buffer
)
{
return EFI_UNSUPPORTED;
}
EFI_STATUS
EFIAPI
Ring3BlockIoFlush (
IN EFI_BLOCK_IO_PROTOCOL *This
)
{
return EFI_UNSUPPORTED;
}
EFI_STATUS
EFIAPI
Ring3DiskIoRead (
IN EFI_DISK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN UINT64 Offset,
IN UINTN BufferSize,
OUT VOID *Buffer
)
{
return EFI_UNSUPPORTED;
}
EFI_STATUS
EFIAPI
Ring3DiskIoWrite (
IN EFI_DISK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN UINT64 Offset,
IN UINTN BufferSize,
IN VOID *Buffer
)
{
return EFI_UNSUPPORTED;
}

View File

@ -11,9 +11,6 @@
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Protocol/DevicePathUtilities.h>
#include <Protocol/LoadedImage.h>
#include "Ring3.h"
EFI_TPL
@ -386,7 +383,9 @@ Ring3OpenProtocol (
{
EFI_STATUS Status;
EFI_LOADED_IMAGE_PROTOCOL *UserProtocol;
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
EFI_BLOCK_IO_PROTOCOL *BlockIo;
EFI_DISK_IO_PROTOCOL *DiskIo;
Status = SysCall (
SysCallOpenProtocol,
@ -403,16 +402,42 @@ Ring3OpenProtocol (
}
if (CompareGuid (Protocol, &gEfiLoadedImageProtocolGuid)) {
UserProtocol = (EFI_LOADED_IMAGE_PROTOCOL *)*Interface;
LoadedImage = (EFI_LOADED_IMAGE_PROTOCOL *)*Interface;
// TODO: Copy User changes to Core? Resembles InstallMultipleProtocolInterfaces().
UserProtocol->Unload = NULL;
LoadedImage->Unload = NULL;
return Status;
} else if (CompareGuid (Protocol, &gEfiBlockIoProtocolGuid)) {
BlockIo = (EFI_BLOCK_IO_PROTOCOL *)*Interface;
mCoreBlockIo.Reset = BlockIo->Reset;
mCoreBlockIo.ReadBlocks = BlockIo->ReadBlocks;
mCoreBlockIo.WriteBlocks = BlockIo->WriteBlocks;
mCoreBlockIo.FlushBlocks = BlockIo->FlushBlocks;
BlockIo->Reset = Ring3BlockIoReset;
BlockIo->ReadBlocks = Ring3BlockIoRead;
BlockIo->WriteBlocks = Ring3BlockIoWrite;
BlockIo->FlushBlocks = Ring3BlockIoFlush;
} else if (CompareGuid (Protocol, &gEfiDiskIoProtocolGuid)) {
DiskIo = (EFI_DISK_IO_PROTOCOL *)*Interface;
mCoreDiskIo.ReadDisk = DiskIo->ReadDisk;
mCoreDiskIo.WriteDisk = DiskIo->WriteDisk;
DiskIo->ReadDisk = Ring3DiskIoRead;
DiskIo->WriteDisk = Ring3DiskIoWrite;
} else {
Status = EFI_UNSUPPORTED;
}
return EFI_UNSUPPORTED;
return Status;
}
EFI_STATUS
@ -473,7 +498,7 @@ Ring3LocateProtocol (
{
EFI_STATUS Status;
EFI_DEVICE_PATH_UTILITIES_PROTOCOL *UserProtocol;
EFI_DEVICE_PATH_UTILITIES_PROTOCOL *DevicePath;
Status = SysCall (
SysCallLocateProtocol,
@ -487,16 +512,16 @@ Ring3LocateProtocol (
}
if (CompareGuid (Protocol, &gEfiDevicePathUtilitiesProtocolGuid)) {
UserProtocol = (EFI_DEVICE_PATH_UTILITIES_PROTOCOL *)*Interface;
DevicePath = (EFI_DEVICE_PATH_UTILITIES_PROTOCOL *)*Interface;
UserProtocol->GetDevicePathSize = NULL;
UserProtocol->DuplicateDevicePath = NULL;
UserProtocol->AppendDevicePath = NULL;
UserProtocol->AppendDeviceNode = NULL;
UserProtocol->AppendDevicePathInstance = NULL;
UserProtocol->GetNextDevicePathInstance = NULL;
UserProtocol->IsDevicePathMultiInstance = NULL;
UserProtocol->CreateDeviceNode = NULL;
DevicePath->GetDevicePathSize = NULL;
DevicePath->DuplicateDevicePath = NULL;
DevicePath->AppendDevicePath = NULL;
DevicePath->AppendDeviceNode = NULL;
DevicePath->AppendDevicePathInstance = NULL;
DevicePath->GetNextDevicePathInstance = NULL;
DevicePath->IsDevicePathMultiInstance = NULL;
DevicePath->CreateDeviceNode = NULL;
return Status;
}

View File

@ -29,23 +29,35 @@ FindGuid (
ASSERT (CoreSize != NULL);
if (CompareGuid (Ring3, &gEfiDevicePathUtilitiesProtocolGuid)) {
*Core = &gEfiDevicePathUtilitiesProtocolGuid;
*CoreSize = sizeof (EFI_DEVICE_PATH_UTILITIES_PROTOCOL);
} else if (CompareGuid (Ring3, &gEfiLoadedImageProtocolGuid)) {
*Core = &gEfiLoadedImageProtocolGuid;
*CoreSize = sizeof (EFI_LOADED_IMAGE_PROTOCOL);
} else if (CompareGuid (Ring3, &gEfiBlockIoProtocolGuid)) {
*Core = &gEfiBlockIoProtocolGuid;
*CoreSize = sizeof (EFI_BLOCK_IO_PROTOCOL);
} else if (CompareGuid (Ring3, &gEfiDiskIoProtocolGuid)) {
*Core = &gEfiDiskIoProtocolGuid;
*CoreSize = sizeof (EFI_DISK_IO_PROTOCOL);
} else if (CompareGuid (Ring3, &gEfiDriverBindingProtocolGuid)) {
*Core = &gEfiDriverBindingProtocolGuid;
*CoreSize = sizeof (EFI_DRIVER_BINDING_PROTOCOL);
} else if (CompareGuid (Ring3, &gEfiComponentNameProtocolGuid)) {
*Core = &gEfiComponentNameProtocolGuid;
*CoreSize = sizeof (EFI_COMPONENT_NAME_PROTOCOL);
} else {
DEBUG ((DEBUG_ERROR, "Ring0: Unknown protocol.\n"));
return EFI_NOT_FOUND;
@ -54,6 +66,26 @@ FindGuid (
return EFI_SUCCESS;
}
VOID
EFIAPI
FixInterface (
IN EFI_GUID *Guid,
IN OUT VOID *Interface
)
{
EFI_BLOCK_IO_PROTOCOL *BlockIo;
if (CompareGuid (Guid, &gEfiBlockIoProtocolGuid)) {
BlockIo = (EFI_BLOCK_IO_PROTOCOL *)Interface;
BlockIo->Media = AllocateRing3Copy (
BlockIo->Media,
sizeof (EFI_BLOCK_IO_MEDIA),
sizeof (EFI_BLOCK_IO_MEDIA)
);
}
}
typedef struct {
UINTN Argument1;
UINTN Argument2;
@ -171,6 +203,8 @@ CallBootService (
return EFI_OUT_OF_RESOURCES;
}
FixInterface (CoreProtocol, Interface);
*(VOID **)CoreRbp->Argument3 = Interface;
EnableSMAP ();
@ -189,6 +223,7 @@ CallBootService (
Status = FindGuid ((EFI_GUID *)UserArgList[Index], (EFI_GUID **)&CoreArgList[Index], &MemoryCoreSize);
if (EFI_ERROR (Status)) {
EnableSMAP ();
//TODO: Free CoreArgList.
return Status;
}