From d59326d3a871f1df6e9416334ca2181ac4373d42 Mon Sep 17 00:00:00 2001 From: andrewfish Date: Tue, 31 May 2011 20:23:36 +0000 Subject: Add BlockIO support to the emulator, still needs testing. Also update Emulator start code to only pass 2 args in place of 3. The 3rd argument is not needed. Still need a function as the BaseLib functoin does not have the correct calling conventions. Cleanup build script for binary shell case. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11718 6f19259b-4bc3-4df7-8a09-765794883524 --- InOsEmuPkg/Unix/Sec/BlockIo.c | 1053 +++++++++++++++++++++++++++++++++ InOsEmuPkg/Unix/Sec/SecMain.c | 1 - InOsEmuPkg/Unix/Sec/SecMain.h | 1 - InOsEmuPkg/Unix/Sec/X64/SwitchStack.S | 13 +- InOsEmuPkg/Unix/UnixX64.dsc | 2 +- InOsEmuPkg/Unix/UnixX64.fdf | 20 +- InOsEmuPkg/Unix/build64.sh | 15 +- 7 files changed, 1073 insertions(+), 32 deletions(-) create mode 100644 InOsEmuPkg/Unix/Sec/BlockIo.c (limited to 'InOsEmuPkg/Unix') diff --git a/InOsEmuPkg/Unix/Sec/BlockIo.c b/InOsEmuPkg/Unix/Sec/BlockIo.c new file mode 100644 index 0000000000..3fc1d3f9aa --- /dev/null +++ b/InOsEmuPkg/Unix/Sec/BlockIo.c @@ -0,0 +1,1053 @@ +/**@file + +Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + UnixBlockIo.c + +Abstract: + + Produce block IO abstractions for real devices on your PC using Posix APIs. + The configuration of what devices to mount or emulate comes from UNIX + environment variables. The variables must be visible to the Microsoft* + Developer Studio for them to work. + + ixed - Fixed disk like a hard drive. + emovable - Removable media like a floppy or CD-ROM. + Read nly - Write protected device. + Read rite - Read write device. + - Decimal number of blocks a device supports. + - Decimal number of bytes per block. + + UNIX envirnonment variable contents. '<' and '>' are not part of the variable, + they are just used to make this help more readable. There should be no + spaces between the ';'. Extra spaces will break the variable. A '!' is + used to seperate multiple devices in a variable. + + EFI_EMU_VIRTUAL_DISKS = + ;;[!...] + + EFI_EMU_PHYSICAL_DISKS = + :;;[!...] + + Virtual Disks: These devices use a file to emulate a hard disk or removable + media device. + + Thus a 20 MB emulated hard drive would look like: + EFI_EMU_VIRTUAL_DISKS=FW;40960;512 + + A 1.44MB emulated floppy with a block size of 1024 would look like: + EFI_EMU_VIRTUAL_DISKS=RW;1440;1024 + + Physical Disks: These devices use UNIX to open a real device in your system + + Thus a 120 MB floppy would look like: + EFI_EMU_PHYSICAL_DISKS=B:RW;245760;512 + + Thus a standard CD-ROM floppy would look like: + EFI_EMU_PHYSICAL_DISKS=Z:RO;307200;2048 + + + * Other names and brands may be claimed as the property of others. + +**/ + +#include +#include +#include "UnixBlockIo.h" + +// +// Block IO protocol member functions +// +EFI_STATUS +EFIAPI +UnixBlockIoReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +UnixBlockIoWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +EFI_STATUS +EFIAPI +UnixBlockIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +UnixBlockIoResetBlock ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +// +// Private Worker functions +// +EFI_STATUS +UnixBlockIoCreateMapping ( + IN EMU_IO_THUNK_PROTOCOL *EmuIoThunk, + IN EFI_HANDLE EfiDeviceHandle, + IN CHAR16 *Filename, + IN BOOLEAN ReadOnly, + IN BOOLEAN RemovableMedia, + IN UINTN NumberOfBlocks, + IN UINTN BlockSize + ); + +EFI_STATUS +UnixBlockIoReadWriteCommon ( + IN EMU_BLOCK_IO_PRIVATE *Private, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer, + IN CHAR8 *CallerName + ); + +EFI_STATUS +UnixBlockIoError ( + IN EMU_BLOCK_IO_PRIVATE *Private + ); + +EFI_STATUS +UnixBlockIoOpenDevice ( + EMU_BLOCK_IO_PRIVATE *Private + ); + +CHAR16 * +GetNextElementPastTerminator ( + IN CHAR16 *EnvironmentVariable, + IN CHAR16 Terminator + ); + + + +EFI_DRIVER_BINDING_PROTOCOL gUnixBlockIoDriverBinding = { + UnixBlockIoDriverBindingSupported, + UnixBlockIoDriverBindingStart, + UnixBlockIoDriverBindingStop, + 0xa, + NULL, + NULL +}; + +/** + The user Entry Point for module UnixBlockIo. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializeUnixBlockIo( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = EfiLibInstallAllDriverProtocols2 ( + ImageHandle, + SystemTable, + &gUnixBlockIoDriverBinding, + ImageHandle, + &gUnixBlockIoComponentName, + &gUnixBlockIoComponentName2, + NULL, + &gUnixBlockIoDriverDiagnostics, + &gUnixBlockIoDriverDiagnostics2 + ); + ASSERT_EFI_ERROR (Status); + + + return Status; +} + +EFI_STATUS +EFIAPI +UnixBlockIoDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +**/ +{ + EFI_STATUS Status; + EMU_IO_THUNK_PROTOCOL *EmuIoThunk; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Handle, + &gEmuIoThunkProtocolGuid, + (VOID **)&EmuIoThunk, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Make sure the UnixThunkProtocol is valid + // + Status = EFI_UNSUPPORTED; + if (EmuIoThunk->UnixThunk->Signature == EFI_EMU_THUNK_PROTOCOL_SIGNATURE) { + + // + // Check the GUID to see if this is a handle type the driver supports + // + if (CompareGuid (EmuIoThunk->TypeGuid, &gEfiUnixVirtualDisksGuid) ) { + Status = EFI_SUCCESS; + } + } + + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + Handle, + &gEmuIoThunkProtocolGuid, + This->DriverBindingHandle, + Handle + ); + return Status; +} + +EFI_STATUS +EFIAPI +UnixBlockIoDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +**/ +{ + EFI_STATUS Status; + EMU_IO_THUNK_PROTOCOL *EmuIoThunk; + CHAR16 Buffer[FILENAME_BUFFER_SIZE]; + CHAR16 *Str; + BOOLEAN RemovableMedia; + BOOLEAN WriteProtected; + UINTN NumberOfBlocks; + UINTN BlockSize; + INTN i; + + // + // Grab the protocols we need + // + + Status = gBS->OpenProtocol ( + Handle, + &gEmuIoThunkProtocolGuid, + (void *)&EmuIoThunk, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Set DiskType + // + if (!CompareGuid (EmuIoThunk->TypeGuid, &gEfiUnixVirtualDisksGuid)) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + Status = EFI_NOT_FOUND; + // Extract filename. + Str = EmuIoThunk->EnvString; + i = 0; + while (*Str && *Str != ':') + Buffer[i++] = *Str++; + Buffer[i] = 0; + if (*Str != ':') { + goto Done; + } + + Str++; + + RemovableMedia = FALSE; + WriteProtected = TRUE; + NumberOfBlocks = 0; + BlockSize = 512; + do { + if (*Str == 'R' || *Str == 'F') { + RemovableMedia = (BOOLEAN) (*Str == 'R'); + Str++; + } + if (*Str == 'O' || *Str == 'W') { + WriteProtected = (BOOLEAN) (*Str == 'O'); + Str++; + } + if (*Str == 0) + break; + if (*Str != ';') + goto Done; + Str++; + + NumberOfBlocks = Atoi (Str); + Str = GetNextElementPastTerminator (Str, ';'); + if (NumberOfBlocks == 0) + break; + + BlockSize = Atoi (Str); + if (BlockSize != 0) + Str = GetNextElementPastTerminator (Str, ';'); + } while (0); + + // + // If we get here the variable is valid so do the work. + // + Status = UnixBlockIoCreateMapping ( + EmuIoThunk, + Handle, + Buffer, + WriteProtected, + RemovableMedia, + NumberOfBlocks, + BlockSize + ); + +Done: + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Handle, + &gEmuIoThunkProtocolGuid, + This->DriverBindingHandle, + Handle + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +UnixBlockIoDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_STATUS Status; + EMU_BLOCK_IO_PRIVATE *Private; + + // + // Get our context back + // + Status = gBS->OpenProtocol ( + Handle, + &gEfiBlockIoProtocolGuid, + (void *)&BlockIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (BlockIo); + + // + // BugBug: If we need to kick people off, we need to make Uninstall Close the handles. + // We could pass in our image handle or FLAG our open to be closed via + // Unistall (== to saying any CloseProtocol will close our open) + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + Private->EfiHandle, + &gEfiBlockIoProtocolGuid, + &Private->BlockIo, + NULL + ); + if (!EFI_ERROR (Status)) { + + Status = gBS->CloseProtocol ( + Handle, + &gEmuIoThunkProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + // + // Shut down our device + // + Private->UnixThunk->Close (Private->fd); + + // + // Free our instance data + // + FreeUnicodeStringTable (Private->ControllerNameTable); + + gBS->FreePool (Private); + } + + return Status; +} + +CHAR16 * +GetNextElementPastTerminator ( + IN CHAR16 *EnvironmentVariable, + IN CHAR16 Terminator + ) +/*++ + +Routine Description: + + Worker function to parse environment variables. + +Arguments: + EnvironmentVariable - Envirnment variable to parse. + + Terminator - Terminator to parse for. + +Returns: + + Pointer to next eliment past the first occurence of Terminator or the '\0' + at the end of the string. + +**/ +{ + CHAR16 *Ptr; + + for (Ptr = EnvironmentVariable; *Ptr != '\0'; Ptr++) { + if (*Ptr == Terminator) { + Ptr++; + break; + } + } + + return Ptr; +} + +EFI_STATUS +UnixBlockIoCreateMapping ( + IN EMU_IO_THUNK_PROTOCOL *EmuIoThunk, + IN EFI_HANDLE EfiDeviceHandle, + IN CHAR16 *Filename, + IN BOOLEAN ReadOnly, + IN BOOLEAN RemovableMedia, + IN UINTN NumberOfBlocks, + IN UINTN BlockSize + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EMU_BLOCK_IO_PRIVATE *Private; + UINTN Index; + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EMU_BLOCK_IO_PRIVATE), + (void *)&Private + ); + ASSERT_EFI_ERROR (Status); + + EfiInitializeLock (&Private->Lock, TPL_NOTIFY); + + Private->UnixThunk = EmuIoThunk->UnixThunk; + + Private->Signature = EMU_BLOCK_IO_PRIVATE_SIGNATURE; + Private->LastBlock = NumberOfBlocks - 1; + Private->BlockSize = BlockSize; + + for (Index = 0; Filename[Index] != 0; Index++) { + Private->Filename[Index] = Filename[Index]; + } + + Private->Filename[Index] = 0; + + Private->Mode = (ReadOnly ? O_RDONLY : O_RDWR); + + Private->NumberOfBlocks = NumberOfBlocks; + Private->fd = -1; + + Private->ControllerNameTable = NULL; + + AddUnicodeString ( + "eng", + gUnixBlockIoComponentName.SupportedLanguages, + &Private->ControllerNameTable, + Filename + ); + + BlockIo = &Private->BlockIo; + BlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION; + BlockIo->Media = &Private->Media; + BlockIo->Media->BlockSize = Private->BlockSize; + BlockIo->Media->LastBlock = Private->NumberOfBlocks - 1; + BlockIo->Media->MediaId = 0;; + + BlockIo->Reset = UnixBlockIoResetBlock; + BlockIo->ReadBlocks = UnixBlockIoReadBlocks; + BlockIo->WriteBlocks = UnixBlockIoWriteBlocks; + BlockIo->FlushBlocks = UnixBlockIoFlushBlocks; + + BlockIo->Media->ReadOnly = ReadOnly; + BlockIo->Media->RemovableMedia = RemovableMedia; + BlockIo->Media->LogicalPartition = FALSE; + BlockIo->Media->MediaPresent = TRUE; + BlockIo->Media->WriteCaching = FALSE; + + BlockIo->Media->IoAlign = 1; + + Private->EfiHandle = EfiDeviceHandle; + Status = UnixBlockIoOpenDevice (Private); + if (!EFI_ERROR (Status)) { + + Status = gBS->InstallMultipleProtocolInterfaces ( + &Private->EfiHandle, + &gEfiBlockIoProtocolGuid, + &Private->BlockIo, + NULL + ); + if (EFI_ERROR (Status)) { + FreeUnicodeStringTable (Private->ControllerNameTable); + gBS->FreePool (Private); + } + + DEBUG ((EFI_D_ERROR, "BlockDevice added: %s\n", Filename)); + } + + return Status; +} + +EFI_STATUS +UnixBlockIoOpenDevice ( + EMU_BLOCK_IO_PRIVATE *Private + ) +{ + EFI_STATUS Status; + UINT64 FileSize; + UINT64 EndOfFile; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + + BlockIo = &Private->BlockIo; + EfiAcquireLock (&Private->Lock); + + // + // If the device is already opened, close it + // + if (Private->fd >= 0) { + BlockIo->Reset (BlockIo, FALSE); + } + + // + // Open the device + // + Private->fd = Private->UnixThunk->Open (Private->Filename, Private->Mode, 0644); + if (Private->fd < 0) { + DEBUG ((EFI_D_INFO, "PlOpenBlock: Could not open %a\n", Private->Filename)); + BlockIo->Media->MediaPresent = FALSE; + Status = EFI_NO_MEDIA; + goto Done; + } + + if (!BlockIo->Media->MediaPresent) { + // + // BugBug: try to emulate if a CD appears - notify drivers to check it out + // + BlockIo->Media->MediaPresent = TRUE; + EfiReleaseLock (&Private->Lock); + EfiAcquireLock (&Private->Lock); + } + + // + // get the size of the file + // + Status = SetFilePointer64 (Private, 0, &FileSize, SEEK_END); + if (EFI_ERROR (Status)) { + FileSize = MultU64x32 (Private->NumberOfBlocks, Private->BlockSize); + DEBUG ((EFI_D_ERROR, "PlOpenBlock: Could not get filesize of %a\n", Private->Filename)); + Status = EFI_UNSUPPORTED; + goto Done; + } + + if (Private->NumberOfBlocks == 0) { + Private->NumberOfBlocks = DivU64x32 (FileSize, Private->BlockSize); + Private->LastBlock = Private->NumberOfBlocks - 1; + Private->Media.LastBlock = Private->LastBlock; + } + + EndOfFile = MultU64x32 (Private->NumberOfBlocks, Private->BlockSize); + + if (FileSize != EndOfFile) { + // + // file is not the proper size, change it + // + DEBUG ((EFI_D_INIT, "PlOpenBlock: Initializing block device: %a\n", Private->Filename)); + + // + // first set it to 0 + // + Private->UnixThunk->FTruncate (Private->fd, 0); + + // + // then set it to the needed file size (OS will zero fill it) + // + Private->UnixThunk->FTruncate (Private->fd, EndOfFile); + } + + DEBUG ((EFI_D_INIT, "%HPlOpenBlock: opened %a%N\n", Private->Filename)); + Status = EFI_SUCCESS; + +Done: + if (EFI_ERROR (Status)) { + if (Private->fd >= 0) { + BlockIo->Reset (BlockIo, FALSE); + } + } + + EfiReleaseLock (&Private->Lock); + return Status; +} + +EFI_STATUS +UnixBlockIoError ( + IN EMU_BLOCK_IO_PRIVATE *Private + ) +{ + return EFI_DEVICE_ERROR; + +#if 0 + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_STATUS Status; + BOOLEAN ReinstallBlockIoFlag; + + + BlockIo = &Private->BlockIo; + + switch (Private->UnixThunk->GetLastError ()) { + + case ERROR_NOT_READY: + Status = EFI_NO_MEDIA; + BlockIo->Media->ReadOnly = FALSE; + BlockIo->Media->MediaPresent = FALSE; + ReinstallBlockIoFlag = FALSE; + break; + + case ERROR_WRONG_DISK: + BlockIo->Media->ReadOnly = FALSE; + BlockIo->Media->MediaPresent = TRUE; + BlockIo->Media->MediaId += 1; + ReinstallBlockIoFlag = TRUE; + Status = EFI_MEDIA_CHANGED; + break; + + case ERROR_WRITE_PROTECT: + BlockIo->Media->ReadOnly = TRUE; + ReinstallBlockIoFlag = FALSE; + Status = EFI_WRITE_PROTECTED; + break; + + default: + ReinstallBlockIoFlag = FALSE; + Status = EFI_DEVICE_ERROR; + break; + } + + if (ReinstallBlockIoFlag) { + BlockIo->Reset (BlockIo, FALSE); + + gBS->ReinstallProtocolInterface ( + Private->EfiHandle, + &gEfiBlockIoProtocolGuid, + BlockIo, + BlockIo + ); + } + + return Status; +#endif +} + +EFI_STATUS +UnixBlockIoReadWriteCommon ( + IN EMU_BLOCK_IO_PRIVATE *Private, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer, + IN CHAR8 *CallerName + ) +{ + EFI_STATUS Status; + UINTN BlockSize; + UINT64 LastBlock; + INT64 DistanceToMove; + UINT64 DistanceMoved; + + if (Private->fd < 0) { + Status = UnixBlockIoOpenDevice (Private); + if (EFI_ERROR (Status)) { + return Status; + } + } + + if (!Private->Media.MediaPresent) { + DEBUG ((EFI_D_INIT, "%s: No Media\n", CallerName)); + return EFI_NO_MEDIA; + } + + if (Private->Media.MediaId != MediaId) { + return EFI_MEDIA_CHANGED; + } + + if ((UINTN) Buffer % Private->Media.IoAlign != 0) { + return EFI_INVALID_PARAMETER; + } + + // + // Verify buffer size + // + BlockSize = Private->BlockSize; + if (BufferSize == 0) { + DEBUG ((EFI_D_INIT, "%s: Zero length read\n", CallerName)); + return EFI_SUCCESS; + } + + if ((BufferSize % BlockSize) != 0) { + DEBUG ((EFI_D_INIT, "%s: Invalid read size\n", CallerName)); + return EFI_BAD_BUFFER_SIZE; + } + + LastBlock = Lba + (BufferSize / BlockSize) - 1; + if (LastBlock > Private->LastBlock) { + DEBUG ((EFI_D_INIT, "ReadBlocks: Attempted to read off end of device\n")); + return EFI_INVALID_PARAMETER; + } + // + // Seek to End of File + // + DistanceToMove = MultU64x32 (Lba, BlockSize); + Status = SetFilePointer64 (Private, DistanceToMove, &DistanceMoved, SEEK_SET); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INIT, "WriteBlocks: SetFilePointer failed\n")); + return UnixBlockIoError (Private); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +UnixBlockIoReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + + Routine Description: + Read BufferSize bytes from Lba into Buffer. + + Arguments: + This - Protocol instance pointer. + MediaId - Id of the media, changes every time the media is replaced. + Lba - The starting Logical Block Address to read from + BufferSize - Size of Buffer, must be a multiple of device block size. + Buffer - Buffer containing read data + + Returns: + EFI_SUCCESS - The data was read correctly from the device. + EFI_DEVICE_ERROR - The device reported an error while performing the read. + EFI_NO_MEDIA - There is no media in the device. + EFI_MEDIA_CHANGED - The MediaId does not matched the current device. + EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the + device. + EFI_INVALID_PARAMETER - The read request contains device addresses that are not + valid for the device. + +**/ +{ + EMU_BLOCK_IO_PRIVATE *Private; + ssize_t len; + EFI_STATUS Status; + EFI_TPL OldTpl; + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This); + + Status = UnixBlockIoReadWriteCommon (Private, MediaId, Lba, BufferSize, Buffer, "UnixReadBlocks"); + if (EFI_ERROR (Status)) { + goto Done; + } + + len = Private->UnixThunk->Read (Private->fd, Buffer, BufferSize); + if (len != BufferSize) { + DEBUG ((EFI_D_INIT, "ReadBlocks: ReadFile failed.\n")); + Status = UnixBlockIoError (Private); + goto Done; + } + + // + // If we wrote then media is present. + // + This->Media->MediaPresent = TRUE; + Status = EFI_SUCCESS; + +Done: + gBS->RestoreTPL (OldTpl); + return Status; +} + +EFI_STATUS +EFIAPI +UnixBlockIoWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ) +/*++ + + Routine Description: + Write BufferSize bytes from Lba into Buffer. + + Arguments: + This - Protocol instance pointer. + MediaId - Id of the media, changes every time the media is replaced. + Lba - The starting Logical Block Address to read from + BufferSize - Size of Buffer, must be a multiple of device block size. + Buffer - Buffer containing read data + + Returns: + EFI_SUCCESS - The data was written correctly to the device. + EFI_WRITE_PROTECTED - The device can not be written to. + EFI_DEVICE_ERROR - The device reported an error while performing the write. + EFI_NO_MEDIA - There is no media in the device. + EFI_MEDIA_CHNAGED - The MediaId does not matched the current device. + EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the + device. + EFI_INVALID_PARAMETER - The write request contains a LBA that is not + valid for the device. + +**/ +{ + EMU_BLOCK_IO_PRIVATE *Private; + ssize_t len; + EFI_STATUS Status; + EFI_TPL OldTpl; + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This); + + Status = UnixBlockIoReadWriteCommon (Private, MediaId, Lba, BufferSize, Buffer, "UnixWriteBlocks"); + if (EFI_ERROR (Status)) { + goto Done; + } + + len = Private->UnixThunk->Write (Private->fd, Buffer, BufferSize); + if (len != BufferSize) { + DEBUG ((EFI_D_INIT, "ReadBlocks: WriteFile failed.\n")); + Status = UnixBlockIoError (Private); + goto Done; + } + + // + // If the write succeeded, we are not write protected and media is present. + // + This->Media->MediaPresent = TRUE; + This->Media->ReadOnly = FALSE; + Status = EFI_SUCCESS; + +Done: + gBS->RestoreTPL (OldTpl); + return Status; +} + +EFI_STATUS +EFIAPI +UnixBlockIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +/*++ + + Routine Description: + Flush the Block Device. + + Arguments: + This - Protocol instance pointer. + + Returns: + EFI_SUCCESS - All outstanding data was written to the device + EFI_DEVICE_ERROR - The device reported an error while writting back the data + EFI_NO_MEDIA - There is no media in the device. + +**/ +{ + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +UnixBlockIoResetBlock ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Reset the Block Device. + + Arguments: + This - Protocol instance pointer. + ExtendedVerification - Driver may perform diagnostics on reset. + + Returns: + EFI_SUCCESS - The device was reset. + EFI_DEVICE_ERROR - The device is not functioning properly and could + not be reset. + +**/ +{ + EMU_BLOCK_IO_PRIVATE *Private; + EFI_TPL OldTpl; + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This); + + if (Private->fd >= 0) { + Private->UnixThunk->Close (Private->fd); + Private->fd = -1; + } + + gBS->RestoreTPL (OldTpl); + + return EFI_SUCCESS; +} + +UINTN +Atoi ( + CHAR16 *String + ) +/*++ + +Routine Description: + + Convert a unicode string to a UINTN + +Arguments: + + String - Unicode string. + +Returns: + + UINTN of the number represented by String. + +**/ +{ + UINTN Number; + CHAR16 *Str; + + // + // skip preceeding white space + // + Str = String; + while ((*Str) && (*Str == ' ')) { + Str++; + } + // + // Convert ot a Number + // + Number = 0; + while (*Str != '\0') { + if ((*Str >= '0') && (*Str <= '9')) { + Number = (Number * 10) +*Str - '0'; + } else { + break; + } + + Str++; + } + + return Number; +} + + +/*++ + +This function extends the capability of SetFilePointer to accept 64 bit parameters + +**/ +EFI_STATUS +SetFilePointer64 ( + IN EMU_BLOCK_IO_PRIVATE *Private, + IN INT64 DistanceToMove, + OUT UINT64 *NewFilePointer, + IN INT32 MoveMethod + ) +{ + EFI_STATUS Status; + off_t res; + + Status = EFI_SUCCESS; + res = Private->UnixThunk->Lseek(Private->fd, DistanceToMove, MoveMethod); + if (res == -1) { + Status = EFI_INVALID_PARAMETER; + } + + if (NewFilePointer != NULL) { + *NewFilePointer = res; + } + + return Status; +} diff --git a/InOsEmuPkg/Unix/Sec/SecMain.c b/InOsEmuPkg/Unix/Sec/SecMain.c index c00268b383..9c0990b2cd 100644 --- a/InOsEmuPkg/Unix/Sec/SecMain.c +++ b/InOsEmuPkg/Unix/Sec/SecMain.c @@ -458,7 +458,6 @@ SecLoadFromCore ( (SWITCH_STACK_ENTRY_POINT) (UINTN) PeiCoreEntryPoint, SecCoreData, (VOID *)gPpiList, - NULL, TopOfStack ); // diff --git a/InOsEmuPkg/Unix/Sec/SecMain.h b/InOsEmuPkg/Unix/Sec/SecMain.h index 00ab7a61ab..19e5f17147 100644 --- a/InOsEmuPkg/Unix/Sec/SecMain.h +++ b/InOsEmuPkg/Unix/Sec/SecMain.h @@ -283,7 +283,6 @@ PeiSwitchStacks ( IN SWITCH_STACK_ENTRY_POINT EntryPoint, IN VOID *Context1, OPTIONAL IN VOID *Context2, OPTIONAL - IN VOID *Context3, OPTIONAL IN VOID *NewStack ); diff --git a/InOsEmuPkg/Unix/Sec/X64/SwitchStack.S b/InOsEmuPkg/Unix/Sec/X64/SwitchStack.S index 76567ac0e1..8a57b781b5 100644 --- a/InOsEmuPkg/Unix/Sec/X64/SwitchStack.S +++ b/InOsEmuPkg/Unix/Sec/X64/SwitchStack.S @@ -16,7 +16,7 @@ #------------------------------------------------------------------------------ # Routine Description: # -# Routine for switching stacks with 3 parameters EFI ABI +# Routine for switching stacks with 2 parameters EFI ABI # Convert UNIX to EFI ABI # # Arguments: @@ -24,8 +24,7 @@ # (rdi) EntryPoint - Entry point with new stack. # (rsi) Context1 - Parameter1 for entry point. (rcx) # (rdx) Context2 - Parameter2 for entry point. (rdx) -# (rcx) Context3 - Parameter3 for entry point. (r8) -# (r8) NewStack - The pointer to new stack. +# (rcx) NewStack - The pointer to new stack. # # Returns: # @@ -37,11 +36,11 @@ ASM_PFX(PeiSwitchStacks): pushq $0 // tells gdb to stop unwinding frame movq %rsp, %rbp - movq %r8, %rsp + movq %rcx, %rsp // update stack pointer - movq %rdi, %rax - movq %rsi, %rcx - movq %rcx, %r8 + movq %rdi, %rax // entry point to %rax + movq %rsi, %rcx // Adjust Context1 + // Context2 already in the rigth spot # # Reserve space for register parameters (rcx, rdx, r8 & r9) on the stack, diff --git a/InOsEmuPkg/Unix/UnixX64.dsc b/InOsEmuPkg/Unix/UnixX64.dsc index dcae0176ff..06b7b34322 100644 --- a/InOsEmuPkg/Unix/UnixX64.dsc +++ b/InOsEmuPkg/Unix/UnixX64.dsc @@ -356,9 +356,9 @@ InOsEmuPkg/EmuBusDriverDxe/EmuBusDriverDxe.inf InOsEmuPkg/EmuGopDxe/EmuGopDxe.inf InOsEmuPkg/EmuSimpleFileSystemDxe/EmuSimpleFileSystemDxe.inf + InOsEmuPkg/EmuBlockIoDxe/EmuBlockIoDxe.inf !if $(0) - UnixPkg/UnixBlockIoDxe/UnixBlockIo.inf UnixPkg/UnixSerialIoDxe/UnixSerialIo.inf UnixPkg/UnixConsoleDxe/UnixConsole.inf UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.inf diff --git a/InOsEmuPkg/Unix/UnixX64.fdf b/InOsEmuPkg/Unix/UnixX64.fdf index 0ba58a39d0..14e5b6022a 100644 --- a/InOsEmuPkg/Unix/UnixX64.fdf +++ b/InOsEmuPkg/Unix/UnixX64.fdf @@ -253,24 +253,18 @@ INF MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf INF FatPkg/EnhancedFatDxe/Fat.inf !else # Used checked in Visual Studio binaries -INF RuleOverride = BINARY USE = X64 FatBinPkg/EnhancedFatDxe/Fat.inf +FILE DRIVER = 961578FE-B6B7-44c3-AF35-6BC705CD2B1F { + SECTION PE32 = FatBinPkg/EnhancedFatDxe/X64/Fat.efi + } !endif !if $(BUILD_NEW_SHELL) INF ShellPkg/Application/Shell/Shell.inf !else -!if $(USE_NEW_SHELL) -INF ShellBinPkg/UefiShell/UefiShell.inf -!else - FILE APPLICATION = PCD(gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile) { -!if $(BUILD_OLD_SHELL) - SECTION PE32 = Build/GccShellPkg/DEBUG_XCLANG/X64/ShellFull.efi -!else - SECTION PE32 = EdkShellBinPkg/FullShell/X64/Shell_Full.efi -!endif - SECTION UI = "Shell" - } -!endif +# Used checked in Visual Studio binaries +FILE APPLICATION = PCD(gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile) { + SECTION PE32 = EdkShellBinPkg/FullShell/X64/Shell_Full.efi + } !endif FILE FREEFORM = PCD(gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile) { diff --git a/InOsEmuPkg/Unix/build64.sh b/InOsEmuPkg/Unix/build64.sh index e575a9266e..a9294be02e 100755 --- a/InOsEmuPkg/Unix/build64.sh +++ b/InOsEmuPkg/Unix/build64.sh @@ -43,7 +43,8 @@ fi TARGET_TOOLS=MYTOOLS UNIXPKG_TOOLS=GCC44 NETWORK_SUPPORT= -COMPILE_BINS= +BUILD_NEW_SHELL= +BUILD_FAT= case `uname` in CYGWIN*) echo Cygwin not fully supported yet. ;; Darwin*) @@ -56,8 +57,9 @@ case `uname` in TARGET_TOOLS=XCODE32 UNIXPKG_TOOLS=XCLANG fi - NETWORK_SUPPORT="-D NETWORK_SUPPORT" - COMPILE_BINS="-D COMPILE_BINS" +# NETWORK_SUPPORT="-D NETWORK_SUPPORT" +# BUILD_NEW_SHELL="-D BUILD_NEW_SHELL" +# BUILD_FAT="-D BUILD_FAT" ;; Linux*) TARGET_TOOLS=ELFGCC ;; @@ -112,11 +114,6 @@ do exit $? fi - if [[ $arg == shell ]]; then - build -p $WORKSPACE/ShellPkg/ShellPkg.dsc -a X64 -t $UNIXPKG_TOOLS -n 3 $2 $3 $4 $5 $6 $7 $8 - cp Build/Shell/DEBUG_$UNIXPKG_TOOLS/X64/Shell.efi ShellBinPkg/UefiShell/X64/Shell.efi - exit $? - fi done @@ -126,7 +123,7 @@ done echo $PATH echo `which build` build -p $WORKSPACE/InOsEmuPkg/Unix/UnixX64.dsc -a X64 -t $TARGET_TOOLS -D SEC_ONLY -n 3 $1 $2 $3 $4 $5 $6 $7 $8 modules -build -p $WORKSPACE/InOsEmuPkg/Unix/UnixX64.dsc -a X64 -t $UNIXPKG_TOOLS $NETWORK_SUPPORT -n 3 $1 $2 $3 $4 $5 $6 $7 $8 +build -p $WORKSPACE/InOsEmuPkg/Unix/UnixX64.dsc -a X64 -t $UNIXPKG_TOOLS $NETWORK_SUPPORT $BUILD_NEW_SHELL $BUILD_FAT -n 3 $1 $2 $3 $4 $5 $6 $7 $8 cp $WORKSPACE/Build/EmuUnixX64/DEBUG_"$TARGET_TOOLS"/X64/SecMain $WORKSPACE/Build/EmuUnixX64/DEBUG_"$UNIXPKG_TOOLS"/X64 exit $? -- cgit v1.2.3