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