diff --git a/MdeModulePkg/Core/Dxe/DxeRing3/DxeRing3.inf b/MdeModulePkg/Core/Dxe/DxeRing3/DxeRing3.inf index 3dbe4b7532..cfcb4d43ed 100644 --- a/MdeModulePkg/Core/Dxe/DxeRing3/DxeRing3.inf +++ b/MdeModulePkg/Core/Dxe/DxeRing3/DxeRing3.inf @@ -25,6 +25,7 @@ Ring3.h DxeRing3.c Ring3UefiBootServices.c + Ring3Protocols.c [Sources.X64] X64/SysCall.nasm diff --git a/MdeModulePkg/Core/Dxe/DxeRing3/Ring3.h b/MdeModulePkg/Core/Dxe/DxeRing3/Ring3.h index 2713748f40..30680d35f2 100644 --- a/MdeModulePkg/Core/Dxe/DxeRing3/Ring3.h +++ b/MdeModulePkg/Core/Dxe/DxeRing3/Ring3.h @@ -5,6 +5,14 @@ **/ +#include +#include +#include +#include + +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 + ); diff --git a/MdeModulePkg/Core/Dxe/DxeRing3/Ring3Protocols.c b/MdeModulePkg/Core/Dxe/DxeRing3/Ring3Protocols.c new file mode 100644 index 0000000000..6bec0eee9e --- /dev/null +++ b/MdeModulePkg/Core/Dxe/DxeRing3/Ring3Protocols.c @@ -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; +} diff --git a/MdeModulePkg/Core/Dxe/DxeRing3/Ring3UefiBootServices.c b/MdeModulePkg/Core/Dxe/DxeRing3/Ring3UefiBootServices.c index c1aec1b883..84b30af06c 100644 --- a/MdeModulePkg/Core/Dxe/DxeRing3/Ring3UefiBootServices.c +++ b/MdeModulePkg/Core/Dxe/DxeRing3/Ring3UefiBootServices.c @@ -11,9 +11,6 @@ #include #include -#include -#include - #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; } diff --git a/MdeModulePkg/Core/Dxe/SysCall/BootServices.c b/MdeModulePkg/Core/Dxe/SysCall/BootServices.c index 24f5c79606..51a24a71b4 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/BootServices.c +++ b/MdeModulePkg/Core/Dxe/SysCall/BootServices.c @@ -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; }