]> git.proxmox.com Git - mirror_edk2.git/blobdiff - InOsEmuPkg/Unix/Sec/BlockIo.c
InOsEmuPkg: Fixed mounting device nodes and .dmg files in the emulator.
[mirror_edk2.git] / InOsEmuPkg / Unix / Sec / BlockIo.c
index 1636d9508c4c501234c14ca4df8e57d60309d383..64494fe83f6a1f79bb9adccf414b8c5a1021ed45 100644 (file)
@@ -30,9 +30,7 @@ typedef struct {
   BOOLEAN                     RemovableMedia;\r
   BOOLEAN                     WriteProtected;\r
 \r
-  UINTN                       BlockSize;\r
   UINT64                      NumberOfBlocks;\r
-  UINT64                      LastBlock;\r
 \r
   EMU_BLOCK_IO_PROTOCOL       EmuBlockIo;\r
   EFI_BLOCK_IO_MEDIA          *Media;\r
@@ -66,12 +64,13 @@ SetFilePointer64 (
 {\r
   EFI_STATUS    Status;\r
   off_t         res;\r
+  off_t         offset = DistanceToMove;\r
 \r
   Status = EFI_SUCCESS;\r
-  res = lseek (Private->fd, DistanceToMove, MoveMethod);\r
+  res = lseek (Private->fd, offset, (int)MoveMethod);\r
   if (res == -1) {\r
     Status = EFI_INVALID_PARAMETER;\r
-  }\r
+  } \r
 \r
   if (NewFilePointer != NULL) {\r
     *NewFilePointer = res;\r
@@ -88,7 +87,7 @@ EmuBlockIoOpenDevice (
 {\r
   EFI_STATUS            Status;\r
   UINT64                FileSize;\r
-  UINT64                EndOfFile;\r
+  struct statfs         buf;\r
 \r
 \r
   //\r
@@ -103,9 +102,9 @@ EmuBlockIoOpenDevice (
   //\r
   Private->fd = open (Private->Filename, Private->Mode, 0644);\r
   if (Private->fd < 0) {\r
-    DEBUG ((EFI_D_INFO, "EmuOpenBlock: Could not open %a\n", Private->Filename));\r
+    printf ("EmuOpenBlock: Could not open %s: %s\n", Private->Filename, strerror(errno));\r
     Private->Media->MediaPresent  = FALSE;\r
-    Status                          = EFI_NO_MEDIA;\r
+    Status                        = EFI_NO_MEDIA;\r
     goto Done;\r
   }\r
 \r
@@ -121,36 +120,54 @@ EmuBlockIoOpenDevice (
   //\r
   Status = SetFilePointer64 (Private, 0, &FileSize, SEEK_END);\r
   if (EFI_ERROR (Status)) {\r
-    FileSize = MultU64x32 (Private->NumberOfBlocks, Private->BlockSize);\r
-    DEBUG ((EFI_D_ERROR, "EmuOpenBlock: Could not get filesize of %a\n", Private->Filename));\r
+    printf ("EmuOpenBlock: Could not get filesize of %s\n", Private->Filename);\r
     Status = EFI_UNSUPPORTED;\r
     goto Done;\r
   }\r
-\r
-  if (Private->NumberOfBlocks == 0) {\r
-    Private->NumberOfBlocks = DivU64x32 (FileSize, Private->BlockSize);\r
-    Private->LastBlock = Private->NumberOfBlocks - 1;\r
-    Private->Media->LastBlock = Private->LastBlock;\r
-  }\r
-\r
-  EndOfFile = MultU64x32 (Private->NumberOfBlocks, Private->BlockSize);\r
-\r
-  if (FileSize != EndOfFile) {\r
-    //\r
-    // file is not the proper size, change it\r
-    //\r
-    DEBUG ((EFI_D_INIT, "EmuOpenBlock: Initializing block device: %a\n", Private->Filename));\r
-\r
-    //\r
-    // first set it to 0\r
-    //\r
-    ftruncate (Private->fd, 0);\r
-\r
+  \r
+  if (FileSize == 0) {\r
+    // lseek fails on a real device. ioctl calls are OS specific\r
+#if __APPLE__\r
+    {\r
+      UINT32 BlockSize;\r
+     \r
+      if (ioctl (Private->fd, DKIOCGETBLOCKSIZE, &BlockSize) == 0) {\r
+        Private->Media->BlockSize = BlockSize;\r
+      }\r
+      if (ioctl (Private->fd, DKIOCGETBLOCKCOUNT, &Private->NumberOfBlocks) == 0) {\r
+        if ((Private->NumberOfBlocks == 0) && (BlockSize == 0x800)) {\r
+          // A DVD is ~ 4.37 GB so make up a number\r
+          Private->Media->LastBlock = (0x100000000ULL/0x800) - 1;\r
+        } else {\r
+          Private->Media->LastBlock = Private->NumberOfBlocks - 1;\r
+        }\r
+      }\r
+      ioctl (Private->fd, DKIOCGETMAXBLOCKCOUNTWRITE, &Private->Media->OptimalTransferLengthGranularity);  \r
+    }\r
+#else \r
+    {\r
+      size_t BlockSize;\r
+      UINT64 DiskSize;\r
+      \r
+      if (ioctl (Private->fd, BLKSSZGET, &BlockSize) == 0) {\r
+        Private->Media->BlockSize = BlockSize;\r
+      }\r
+      if (ioctl (Private->fd, BLKGETSIZE64, &DiskSize) == 0) {\r
+        Private->NumberOfBlocks = DivU64x32 (DiskSize, (UINT32)BlockSize);\r
+        Private->Media->LastBlock = Private->NumberOfBlocks - 1;\r
+      }\r
+    }\r
+#endif\r
+    \r
+  } else if (fstatfs (Private->fd, &buf) == 0) {\r
     //\r
-    // then set it to the needed file size (OS will zero fill it)\r
+    // Works for files, not devices\r
     //\r
-    ftruncate (Private->fd, EndOfFile);\r
-  }\r
+    Private->Media->BlockSize = buf.f_bsize;\r
+    Private->Media->OptimalTransferLengthGranularity = buf.f_iosize/buf.f_bsize;\r
+    Private->NumberOfBlocks = DivU64x32 (FileSize, Private->Media->BlockSize);\r
+    Private->Media->LastBlock = Private->NumberOfBlocks - 1;\r
+  } \r
 \r
   DEBUG ((EFI_D_INIT, "%HEmuOpenBlock: opened %a%N\n", Private->Filename));\r
   Status = EFI_SUCCESS;\r
@@ -185,19 +202,20 @@ EmuBlockIoCreateMapping (
   Media->LogicalPartition = FALSE;\r
   Media->ReadOnly         = Private->WriteProtected;\r
   Media->WriteCaching     = FALSE;\r
-  Media->BlockSize        = Private->BlockSize;\r
   Media->IoAlign          = 1;\r
   Media->LastBlock        = 0; // Filled in by OpenDevice\r
   \r
   // EFI_BLOCK_IO_PROTOCOL_REVISION2\r
   Media->LowestAlignedLba              = 0;\r
   Media->LogicalBlocksPerPhysicalBlock = 0; \r
-  \r
+    \r
+\r
   // EFI_BLOCK_IO_PROTOCOL_REVISION3\r
   Media->OptimalTransferLengthGranularity = 0;\r
-\r
+    \r
   Status = EmuBlockIoOpenDevice (Private);\r
 \r
+  \r
   return Status;\r
 }\r
 \r
@@ -293,7 +311,7 @@ EmuBlockIoReadWriteCommon (
   //\r
   // Verify buffer size\r
   //\r
-  BlockSize = Private->BlockSize;\r
+  BlockSize = Private->Media->BlockSize;\r
   if (BufferSize == 0) {\r
     DEBUG ((EFI_D_INIT, "%s: Zero length read\n", CallerName));\r
     return EFI_SUCCESS;\r
@@ -305,7 +323,7 @@ EmuBlockIoReadWriteCommon (
   }\r
 \r
   LastBlock = Lba + (BufferSize / BlockSize) - 1;\r
-  if (LastBlock > Private->LastBlock) {\r
+  if (LastBlock > Private->Media->LastBlock) {\r
     DEBUG ((EFI_D_INIT, "ReadBlocks: Attempted to read off end of device\n"));\r
     return EFI_INVALID_PARAMETER;\r
   }\r
@@ -512,14 +530,15 @@ EmuBlockIoFlushBlocks (
   )\r
 {\r
   EMU_BLOCK_IO_PRIVATE *Private;\r
+  int                  Res;\r
 \r
   Private = EMU_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);\r
 \r
   if (Private->fd >= 0) {\r
-    close (Private->fd);\r
-    Private->fd = open (Private->Filename, Private->Mode, 0644);\r
+    Res = fcntl (Private->fd, F_FULLFSYNC);\r
   }\r
   \r
+  \r
   if (Token != NULL) {\r
     if (Token->Event != NULL) {\r
       // Caller is responcible for signaling EFI Event\r
@@ -658,8 +677,6 @@ EmuBlockIoThunkOpen (
     }\r
   }\r
   \r
-  Private->BlockSize = 512;\r
\r
   This->Interface = &Private->EmuBlockIo;\r
   This->Private   = Private;\r
   return EFI_SUCCESS;\r