Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

343 lines
7.5 KiB

  1. /*++
  2. Copyright (c) 1998 Intel Corporation
  3. Module Name:
  4. sread.c
  5. Abstract:
  6. Simple read file access
  7. Revision History
  8. --*/
  9. #include "lib.h"
  10. #define SIMPLE_READ_SIGNATURE EFI_SIGNATURE_32('s','r','d','r')
  11. typedef struct _SIMPLE_READ_FILE {
  12. UINTN Signature;
  13. BOOLEAN FreeBuffer;
  14. VOID *Source;
  15. UINTN SourceSize;
  16. EFI_FILE_HANDLE FileHandle;
  17. } SIMPLE_READ_HANDLE;
  18. EFI_STATUS
  19. OpenSimpleReadFile (
  20. IN BOOLEAN BootPolicy,
  21. IN VOID *SourceBuffer OPTIONAL,
  22. IN UINTN SourceSize,
  23. IN OUT EFI_DEVICE_PATH **FilePath,
  24. OUT EFI_HANDLE *DeviceHandle,
  25. OUT SIMPLE_READ_FILE *SimpleReadHandle
  26. )
  27. /*++
  28. Routine Description:
  29. Opens a file for (simple) reading. The simple read abstraction
  30. will access the file either from a memory copy, from a file
  31. system interface, or from the load file interface.
  32. Arguments:
  33. Returns:
  34. A handle to access the file
  35. --*/
  36. {
  37. SIMPLE_READ_HANDLE *FHand;
  38. EFI_DEVICE_PATH *UserFilePath;
  39. FILEPATH_DEVICE_PATH *FilePathNode;
  40. EFI_FILE_HANDLE FileHandle, LastHandle;
  41. EFI_STATUS Status;
  42. EFI_LOAD_FILE_INTERFACE *LoadFile;
  43. FHand = NULL;
  44. UserFilePath = *FilePath;
  45. /*
  46. * Allocate a new simple read handle structure
  47. */
  48. FHand = AllocateZeroPool (sizeof(SIMPLE_READ_HANDLE));
  49. if (!FHand) {
  50. Status = EFI_OUT_OF_RESOURCES;
  51. goto Done;
  52. }
  53. *SimpleReadHandle = (SIMPLE_READ_FILE) FHand;
  54. FHand->Signature = SIMPLE_READ_SIGNATURE;
  55. /*
  56. * If the caller passed a copy of the file, then just use it
  57. */
  58. if (SourceBuffer) {
  59. FHand->Source = SourceBuffer;
  60. FHand->SourceSize = SourceSize;
  61. *DeviceHandle = NULL;
  62. Status = EFI_SUCCESS;
  63. goto Done;
  64. }
  65. /*
  66. * Attempt to access the file via a file system interface
  67. */
  68. FileHandle = NULL;
  69. Status = BS->LocateDevicePath (&FileSystemProtocol, FilePath, DeviceHandle);
  70. if (!EFI_ERROR(Status)) {
  71. FileHandle = LibOpenRoot (*DeviceHandle);
  72. }
  73. Status = FileHandle ? EFI_SUCCESS : EFI_UNSUPPORTED;
  74. /*
  75. * To access as a filesystem, the filepath should only
  76. * contain filepath components. Follow the filepath nodes
  77. * and find the target file
  78. */
  79. FilePathNode = (FILEPATH_DEVICE_PATH *) *FilePath;
  80. while (!IsDevicePathEnd(&FilePathNode->Header)) {
  81. /*
  82. * For filesystem access each node should be a filepath component
  83. */
  84. if (DevicePathType(&FilePathNode->Header) != MEDIA_DEVICE_PATH ||
  85. DevicePathSubType(&FilePathNode->Header) != MEDIA_FILEPATH_DP) {
  86. Status = EFI_UNSUPPORTED;
  87. }
  88. /*
  89. * If there's been an error, stop
  90. */
  91. if (EFI_ERROR(Status)) {
  92. break;
  93. }
  94. /*
  95. * Open this file path node
  96. */
  97. LastHandle = FileHandle;
  98. FileHandle = NULL;
  99. Status = LastHandle->Open (
  100. LastHandle,
  101. &FileHandle,
  102. FilePathNode->PathName,
  103. EFI_FILE_MODE_READ,
  104. 0
  105. );
  106. /*
  107. * Close the last node
  108. */
  109. LastHandle->Close (LastHandle);
  110. /*
  111. * Get the next node
  112. */
  113. FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode(&FilePathNode->Header);
  114. }
  115. /*
  116. * If success, return the FHand
  117. */
  118. if (!EFI_ERROR(Status)) {
  119. ASSERT(FileHandle);
  120. FHand->FileHandle = FileHandle;
  121. goto Done;
  122. }
  123. /*
  124. * Cleanup from filesystem access
  125. */
  126. if (FileHandle) {
  127. FileHandle->Close (FileHandle);
  128. FileHandle = NULL;
  129. *FilePath = UserFilePath;
  130. }
  131. /*
  132. * If the error is something other then unsupported, return it
  133. */
  134. if (Status != EFI_UNSUPPORTED) {
  135. goto Done;
  136. }
  137. /*
  138. * Attempt to access the file via the load file protocol
  139. */
  140. Status = LibDevicePathToInterface (&LoadFileProtocol, *FilePath, (VOID*)&LoadFile);
  141. if (!EFI_ERROR(Status)) {
  142. /*
  143. * Determine the size of buffer needed to hold the file
  144. */
  145. SourceSize = 0;
  146. Status = LoadFile->LoadFile (
  147. LoadFile,
  148. *FilePath,
  149. BootPolicy,
  150. &SourceSize,
  151. NULL
  152. );
  153. /*
  154. * We expect a buffer too small error to inform us
  155. * of the buffer size needed
  156. */
  157. if (Status == EFI_BUFFER_TOO_SMALL) {
  158. SourceBuffer = AllocatePool (SourceSize);
  159. if (SourceBuffer) {
  160. FHand->FreeBuffer = TRUE;
  161. FHand->Source = SourceBuffer;
  162. FHand->SourceSize = SourceSize;
  163. Status = LoadFile->LoadFile (
  164. LoadFile,
  165. *FilePath,
  166. BootPolicy,
  167. &SourceSize,
  168. SourceBuffer
  169. );
  170. }
  171. }
  172. /*
  173. * If success, return FHand
  174. */
  175. if (!EFI_ERROR(Status)) {
  176. goto Done;
  177. }
  178. }
  179. /*
  180. * Nothing else to try
  181. */
  182. DEBUG ((D_LOAD|D_WARN, "OpenSimpleReadFile: Device did not support a known load protocol\n"));
  183. Status = EFI_UNSUPPORTED;
  184. Done:
  185. /*
  186. * If the file was not accessed, clean up
  187. */
  188. if (EFI_ERROR(Status)) {
  189. if (FHand) {
  190. if (FHand->FreeBuffer) {
  191. FreePool (FHand->Source);
  192. }
  193. FreePool (FHand);
  194. }
  195. }
  196. return Status;
  197. }
  198. EFI_STATUS
  199. ReadSimpleReadFile (
  200. IN SIMPLE_READ_FILE UserHandle,
  201. IN UINTN Offset,
  202. IN OUT UINTN *ReadSize,
  203. OUT VOID *Buffer
  204. )
  205. {
  206. UINTN EndPos;
  207. SIMPLE_READ_HANDLE *FHand;
  208. EFI_STATUS Status;
  209. FHand = UserHandle;
  210. ASSERT (FHand->Signature == SIMPLE_READ_SIGNATURE);
  211. if (FHand->Source) {
  212. /*
  213. * Move data from our local copy of the file
  214. */
  215. EndPos = Offset + *ReadSize;
  216. if (EndPos > FHand->SourceSize) {
  217. *ReadSize = FHand->SourceSize - Offset;
  218. if (Offset >= FHand->SourceSize) {
  219. *ReadSize = 0;
  220. }
  221. }
  222. CopyMem (Buffer, (CHAR8 *) FHand->Source + Offset, *ReadSize);
  223. Status = EFI_SUCCESS;
  224. } else {
  225. /*
  226. * Read data from the file
  227. */
  228. Status = FHand->FileHandle->SetPosition (FHand->FileHandle, Offset);
  229. if (!EFI_ERROR(Status)) {
  230. Status = FHand->FileHandle->Read (FHand->FileHandle, ReadSize, Buffer);
  231. }
  232. }
  233. return Status;
  234. }
  235. VOID
  236. CloseSimpleReadFile (
  237. IN SIMPLE_READ_FILE UserHandle
  238. )
  239. {
  240. SIMPLE_READ_HANDLE *FHand;
  241. FHand = UserHandle;
  242. ASSERT (FHand->Signature == SIMPLE_READ_SIGNATURE);
  243. /*
  244. * Free any file handle we opened
  245. */
  246. if (FHand->FileHandle) {
  247. FHand->FileHandle->Close (FHand->FileHandle);
  248. }
  249. /*
  250. * If we allocated the Source buffer, free it
  251. */
  252. if (FHand->FreeBuffer) {
  253. FreePool (FHand->Source);
  254. }
  255. /*
  256. * Done with this simple read file handle
  257. */
  258. FreePool (FHand);
  259. }