summaryrefslogtreecommitdiff
path: root/EmulatorPkg/Unix/Host/BlockIo.c
diff options
context:
space:
mode:
Diffstat (limited to 'EmulatorPkg/Unix/Host/BlockIo.c')
-rw-r--r--EmulatorPkg/Unix/Host/BlockIo.c708
1 files changed, 0 insertions, 708 deletions
diff --git a/EmulatorPkg/Unix/Host/BlockIo.c b/EmulatorPkg/Unix/Host/BlockIo.c
deleted file mode 100644
index fa05fbc107..0000000000
--- a/EmulatorPkg/Unix/Host/BlockIo.c
+++ /dev/null
@@ -1,708 +0,0 @@
-/**@file
-
-Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR>
-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.
-
-**/
-
-#include "Host.h"
-
-#define EMU_BLOCK_IO_PRIVATE_SIGNATURE SIGNATURE_32 ('E', 'M', 'b', 'k')
-typedef struct {
- UINTN Signature;
-
- EMU_IO_THUNK_PROTOCOL *Thunk;
-
- char *Filename;
- UINTN ReadMode;
- UINTN Mode;
-
- int fd;
-
- BOOLEAN RemovableMedia;
- BOOLEAN WriteProtected;
-
- UINT64 NumberOfBlocks;
- UINT32 BlockSize;
-
- EMU_BLOCK_IO_PROTOCOL EmuBlockIo;
- EFI_BLOCK_IO_MEDIA *Media;
-
-} EMU_BLOCK_IO_PRIVATE;
-
-#define EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS(a) \
- CR(a, EMU_BLOCK_IO_PRIVATE, EmuBlockIo, EMU_BLOCK_IO_PRIVATE_SIGNATURE)
-
-
-
-EFI_STATUS
-EmuBlockIoReset (
- IN EMU_BLOCK_IO_PROTOCOL *This,
- IN BOOLEAN ExtendedVerification
- );
-
-
-/*++
-
-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;
- off_t offset = DistanceToMove;
-
- Status = EFI_SUCCESS;
- res = lseek (Private->fd, offset, (int)MoveMethod);
- if (res == -1) {
- Status = EFI_INVALID_PARAMETER;
- }
-
- if (NewFilePointer != NULL) {
- *NewFilePointer = res;
- }
-
- return Status;
-}
-
-
-EFI_STATUS
-EmuBlockIoOpenDevice (
- IN EMU_BLOCK_IO_PRIVATE *Private
- )
-{
- EFI_STATUS Status;
- UINT64 FileSize;
- struct statfs buf;
-
-
- //
- // If the device is already opened, close it
- //
- if (Private->fd >= 0) {
- EmuBlockIoReset (&Private->EmuBlockIo, FALSE);
- }
-
- //
- // Open the device
- //
- Private->fd = open (Private->Filename, Private->Mode, 0644);
- if (Private->fd < 0) {
- printf ("EmuOpenBlock: Could not open %s: %s\n", Private->Filename, strerror(errno));
- Private->Media->MediaPresent = FALSE;
- Status = EFI_NO_MEDIA;
- goto Done;
- }
-
- if (!Private->Media->MediaPresent) {
- //
- // BugBug: try to emulate if a CD appears - notify drivers to check it out
- //
- Private->Media->MediaPresent = TRUE;
- }
-
- //
- // get the size of the file
- //
- Status = SetFilePointer64 (Private, 0, &FileSize, SEEK_END);
- if (EFI_ERROR (Status)) {
- printf ("EmuOpenBlock: Could not get filesize of %s\n", Private->Filename);
- Status = EFI_UNSUPPORTED;
- goto Done;
- }
-
- if (FileSize == 0) {
- // lseek fails on a real device. ioctl calls are OS specific
-#if __APPLE__
- {
- UINT32 BlockSize;
-
- if (ioctl (Private->fd, DKIOCGETBLOCKSIZE, &BlockSize) == 0) {
- Private->Media->BlockSize = BlockSize;
- }
- if (ioctl (Private->fd, DKIOCGETBLOCKCOUNT, &Private->NumberOfBlocks) == 0) {
- if ((Private->NumberOfBlocks == 0) && (BlockSize == 0x800)) {
- // A DVD is ~ 4.37 GB so make up a number
- Private->Media->LastBlock = (0x100000000ULL/0x800) - 1;
- } else {
- Private->Media->LastBlock = Private->NumberOfBlocks - 1;
- }
- }
- ioctl (Private->fd, DKIOCGETMAXBLOCKCOUNTWRITE, &Private->Media->OptimalTransferLengthGranularity);
- }
-#else
- {
- size_t BlockSize;
- UINT64 DiskSize;
-
- if (ioctl (Private->fd, BLKSSZGET, &BlockSize) == 0) {
- Private->Media->BlockSize = BlockSize;
- }
- if (ioctl (Private->fd, BLKGETSIZE64, &DiskSize) == 0) {
- Private->NumberOfBlocks = DivU64x32 (DiskSize, (UINT32)BlockSize);
- Private->Media->LastBlock = Private->NumberOfBlocks - 1;
- }
- }
-#endif
-
- } else {
- Private->Media->BlockSize = Private->BlockSize;
- Private->NumberOfBlocks = DivU64x32 (FileSize, Private->Media->BlockSize);
- Private->Media->LastBlock = Private->NumberOfBlocks - 1;
-
- if (fstatfs (Private->fd, &buf) == 0) {
-#if __APPLE__
- Private->Media->OptimalTransferLengthGranularity = buf.f_iosize/buf.f_bsize;
-#else
- Private->Media->OptimalTransferLengthGranularity = buf.f_bsize/buf.f_bsize;
-#endif
- }
- }
-
- DEBUG ((EFI_D_INIT, "%HEmuOpenBlock: opened %a%N\n", Private->Filename));
- Status = EFI_SUCCESS;
-
-Done:
- if (EFI_ERROR (Status)) {
- if (Private->fd >= 0) {
- EmuBlockIoReset (&Private->EmuBlockIo, FALSE);
- }
- }
-
- return Status;
-}
-
-
-EFI_STATUS
-EmuBlockIoCreateMapping (
- IN EMU_BLOCK_IO_PROTOCOL *This,
- IN EFI_BLOCK_IO_MEDIA *Media
- )
-{
- EFI_STATUS Status;
- EMU_BLOCK_IO_PRIVATE *Private;
-
- Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
-
- Private->Media = Media;
-
- Media->MediaId = 0;
- Media->RemovableMedia = Private->RemovableMedia;
- Media->MediaPresent = TRUE;
- Media->LogicalPartition = FALSE;
- Media->ReadOnly = Private->WriteProtected;
- Media->WriteCaching = FALSE;
- Media->IoAlign = 1;
- Media->LastBlock = 0; // Filled in by OpenDevice
-
- // EFI_BLOCK_IO_PROTOCOL_REVISION2
- Media->LowestAlignedLba = 0;
- Media->LogicalBlocksPerPhysicalBlock = 0;
-
-
- // EFI_BLOCK_IO_PROTOCOL_REVISION3
- Media->OptimalTransferLengthGranularity = 0;
-
- Status = EmuBlockIoOpenDevice (Private);
-
-
- return Status;
-}
-
-
-EFI_STATUS
-EmuBlockIoError (
- IN EMU_BLOCK_IO_PRIVATE *Private
- )
-{
- EFI_STATUS Status;
- BOOLEAN ReinstallBlockIoFlag;
-
-
- switch (errno) {
-
- case EAGAIN:
- Status = EFI_NO_MEDIA;
- Private->Media->ReadOnly = FALSE;
- Private->Media->MediaPresent = FALSE;
- ReinstallBlockIoFlag = FALSE;
- break;
-
- case EACCES:
- Private->Media->ReadOnly = FALSE;
- Private->Media->MediaPresent = TRUE;
- Private->Media->MediaId += 1;
- ReinstallBlockIoFlag = TRUE;
- Status = EFI_MEDIA_CHANGED;
- break;
-
- case EROFS:
- Private->Media->ReadOnly = TRUE;
- ReinstallBlockIoFlag = FALSE;
- Status = EFI_WRITE_PROTECTED;
- break;
-
- default:
- ReinstallBlockIoFlag = FALSE;
- Status = EFI_DEVICE_ERROR;
- break;
- }
- return Status;
-}
-
-
-EFI_STATUS
-EmuBlockIoReadWriteCommon (
- 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 = EmuBlockIoOpenDevice (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->Media->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->Media->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 EmuBlockIoError (Private);
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Read BufferSize bytes from Lba into Buffer.
-
- This function reads the requested number of blocks from the device. All the
- blocks are read, or an error is returned.
- If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and
- non-blocking I/O is being used, the Event associated with this request will
- not be signaled.
-
- @param[in] This Indicates a pointer to the calling context.
- @param[in] MediaId Id of the media, changes every time the media is
- replaced.
- @param[in] Lba The starting Logical Block Address to read from.
- @param[in, out] Token A pointer to the token associated with the transaction.
- @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
- @param[out] 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 read request was queued if Token->Event is
- not NULL.The data was read correctly from the
- device if the Token->Event is NULL.
- @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 is not for the current media.
- @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
- intrinsic 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.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
- of resources.
-**/
-EFI_STATUS
-EmuBlockIoReadBlocks (
- IN EMU_BLOCK_IO_PROTOCOL *This,
- IN UINT32 MediaId,
- IN EFI_LBA LBA,
- IN OUT EFI_BLOCK_IO2_TOKEN *Token,
- IN UINTN BufferSize,
- OUT VOID *Buffer
- )
-{
- EFI_STATUS Status;
- EMU_BLOCK_IO_PRIVATE *Private;
- ssize_t len;
-
- Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
-
- Status = EmuBlockIoReadWriteCommon (Private, MediaId, LBA, BufferSize, Buffer, "UnixReadBlocks");
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- len = read (Private->fd, Buffer, BufferSize);
- if (len != BufferSize) {
- DEBUG ((EFI_D_INIT, "ReadBlocks: ReadFile failed.\n"));
- Status = EmuBlockIoError (Private);
- goto Done;
- }
-
- //
- // If we read then media is present.
- //
- Private->Media->MediaPresent = TRUE;
- Status = EFI_SUCCESS;
-
-Done:
- if (Token != NULL) {
- if (Token->Event != NULL) {
- // Caller is responcible for signaling EFI Event
- Token->TransactionStatus = Status;
- return EFI_SUCCESS;
- }
- }
- return Status;
-}
-
-
-/**
- Write BufferSize bytes from Lba into Buffer.
-
- This function writes the requested number of blocks to the device. All blocks
- are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA,
- EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is
- being used, the Event associated with this request will not be signaled.
-
- @param[in] This Indicates a pointer to the calling context.
- @param[in] MediaId The media ID that the write request is for.
- @param[in] Lba The starting logical block address to be written. The
- caller is responsible for writing to only legitimate
- locations.
- @param[in, out] Token A pointer to the token associated with the transaction.
- @param[in] BufferSize Size of Buffer, must be a multiple of device block size.
- @param[in] Buffer A pointer to the source buffer for the data.
-
- @retval EFI_SUCCESS The write request was queued if Event is not NULL.
- The data was written correctly to the device if
- the Event is NULL.
- @retval EFI_WRITE_PROTECTED The device can not be written to.
- @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_DEVICE_ERROR The device reported an error while performing the write.
- @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.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
- of resources.
-
-**/
-EFI_STATUS
-EmuBlockIoWriteBlocks (
- IN EMU_BLOCK_IO_PROTOCOL *This,
- IN UINT32 MediaId,
- IN EFI_LBA LBA,
- IN OUT EFI_BLOCK_IO2_TOKEN *Token,
- IN UINTN BufferSize,
- IN VOID *Buffer
- )
-{
- EMU_BLOCK_IO_PRIVATE *Private;
- ssize_t len;
- EFI_STATUS Status;
-
-
- Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
-
- Status = EmuBlockIoReadWriteCommon (Private, MediaId, LBA, BufferSize, Buffer, "UnixWriteBlocks");
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- len = write (Private->fd, Buffer, BufferSize);
- if (len != BufferSize) {
- DEBUG ((EFI_D_INIT, "ReadBlocks: WriteFile failed.\n"));
- Status = EmuBlockIoError (Private);
- goto Done;
- }
-
- //
- // If the write succeeded, we are not write protected and media is present.
- //
- Private->Media->MediaPresent = TRUE;
- Private->Media->ReadOnly = FALSE;
- Status = EFI_SUCCESS;
-
-Done:
- if (Token != NULL) {
- if (Token->Event != NULL) {
- // Caller is responcible for signaling EFI Event
- Token->TransactionStatus = Status;
- return EFI_SUCCESS;
- }
- }
-
- return Status;
-}
-
-
-/**
- Flush the Block Device.
-
- If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED
- is returned and non-blocking I/O is being used, the Event associated with
- this request will not be signaled.
-
- @param[in] This Indicates a pointer to the calling context.
- @param[in,out] Token A pointer to the token associated with the transaction
-
- @retval EFI_SUCCESS The flush request was queued if Event is not NULL.
- All outstanding data was written correctly to the
- device if the Event is NULL.
- @retval EFI_DEVICE_ERROR The device reported an error while writting back
- the data.
- @retval EFI_WRITE_PROTECTED The device cannot be written to.
- @retval EFI_NO_MEDIA There is no media in the device.
- @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
- of resources.
-
-**/
-EFI_STATUS
-EmuBlockIoFlushBlocks (
- IN EMU_BLOCK_IO_PROTOCOL *This,
- IN OUT EFI_BLOCK_IO2_TOKEN *Token
- )
-{
- EMU_BLOCK_IO_PRIVATE *Private;
-
- Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
-
- if (Private->fd >= 0) {
- fsync (Private->fd);
-#if __APPLE__
- fcntl (Private->fd, F_FULLFSYNC);
-#endif
- }
-
-
- if (Token != NULL) {
- if (Token->Event != NULL) {
- // Caller is responcible for signaling EFI Event
- Token->TransactionStatus = EFI_SUCCESS;
- return EFI_SUCCESS;
- }
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Reset the block device hardware.
-
- @param[in] This Indicates a pointer to the calling context.
- @param[in] ExtendedVerification Indicates that the driver may perform a more
- exhausive verfication operation of the device
- during 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
-EmuBlockIoReset (
- IN EMU_BLOCK_IO_PROTOCOL *This,
- IN BOOLEAN ExtendedVerification
- )
-{
- EMU_BLOCK_IO_PRIVATE *Private;
-
- Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
-
- if (Private->fd >= 0) {
- close (Private->fd);
- Private->fd = -1;
- }
-
- return EFI_SUCCESS;
-}
-
-
-char *
-StdDupUnicodeToAscii (
- IN CHAR16 *Str
- )
-{
- UINTN Size;
- char *Ascii;
- char *Ptr;
-
- Size = StrLen (Str) + 1;
- Ascii = malloc (Size);
- if (Ascii == NULL) {
- return NULL;
- }
-
- for (Ptr = Ascii; *Str != '\0'; Ptr++, Str++) {
- *Ptr = *Str;
- }
- *Ptr = 0;
-
- return Ascii;
-}
-
-
-EMU_BLOCK_IO_PROTOCOL gEmuBlockIoProtocol = {
- GasketEmuBlockIoReset,
- GasketEmuBlockIoReadBlocks,
- GasketEmuBlockIoWriteBlocks,
- GasketEmuBlockIoFlushBlocks,
- GasketEmuBlockIoCreateMapping
-};
-
-EFI_STATUS
-EmuBlockIoThunkOpen (
- IN EMU_IO_THUNK_PROTOCOL *This
- )
-{
- EMU_BLOCK_IO_PRIVATE *Private;
- char *Str;
-
- if (This->Private != NULL) {
- return EFI_ALREADY_STARTED;
- }
-
- if (!CompareGuid (This->Protocol, &gEmuBlockIoProtocolGuid)) {
- return EFI_UNSUPPORTED;
- }
-
- Private = malloc (sizeof (EMU_BLOCK_IO_PRIVATE));
- if (Private == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
-
- Private->Signature = EMU_BLOCK_IO_PRIVATE_SIGNATURE;
- Private->Thunk = This;
- CopyMem (&Private->EmuBlockIo, &gEmuBlockIoProtocol, sizeof (gEmuBlockIoProtocol));
- Private->fd = -1;
- Private->BlockSize = 512;
-
- Private->Filename = StdDupUnicodeToAscii (This->ConfigString);
- if (Private->Filename == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- Str = strstr (Private->Filename, ":");
- if (Str == NULL) {
- Private->RemovableMedia = FALSE;
- Private->WriteProtected = FALSE;
- } else {
- for (*Str++ = '\0'; *Str != 0; Str++) {
- if (*Str == 'R' || *Str == 'F') {
- Private->RemovableMedia = (BOOLEAN) (*Str == 'R');
- }
- if (*Str == 'O' || *Str == 'W') {
- Private->WriteProtected = (BOOLEAN) (*Str == 'O');
- }
- if (*Str == ':') {
- Private->BlockSize = strtol (++Str, NULL, 0);
- break;
- }
- }
- }
-
- Private->Mode = Private->WriteProtected ? O_RDONLY : O_RDWR;
-
- This->Interface = &Private->EmuBlockIo;
- This->Private = Private;
- return EFI_SUCCESS;
-}
-
-
-EFI_STATUS
-EmuBlockIoThunkClose (
- IN EMU_IO_THUNK_PROTOCOL *This
- )
-{
- EMU_BLOCK_IO_PRIVATE *Private;
-
- if (!CompareGuid (This->Protocol, &gEmuBlockIoProtocolGuid)) {
- return EFI_UNSUPPORTED;
- }
-
- Private = This->Private;
-
- if (This->Private != NULL) {
- if (Private->Filename != NULL) {
- free (Private->Filename);
- }
- free (This->Private);
- This->Private = NULL;
- }
-
- return EFI_SUCCESS;
-}
-
-
-
-EMU_IO_THUNK_PROTOCOL gBlockIoThunkIo = {
- &gEmuBlockIoProtocolGuid,
- NULL,
- NULL,
- 0,
- GasketBlockIoThunkOpen,
- GasketBlockIoThunkClose,
- NULL
-};
-
-