1// Copyright 2016 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <efi/protocol/loaded-image.h> 6#include <efi/protocol/simple-file-system.h> 7 8#include <xefi.h> 9#include <stdio.h> 10 11#ifndef VERBOSE 12#define xprintf(...) do {} while (0); 13#else 14#define xprintf(fmt...) printf(fmt) 15#endif 16 17efi_file_protocol* xefi_open_file(char16_t* filename) { 18 efi_loaded_image_protocol* loaded; 19 efi_status r; 20 efi_file_protocol* file = NULL; 21 22 r = xefi_open_protocol(gImg, &LoadedImageProtocol, (void**)&loaded); 23 if (r) { 24 xprintf("LoadFile: Cannot open LoadedImageProtocol (%s)\n", xefi_strerror(r)); 25 goto exit0; 26 } 27 28#if 0 29 printf("Img DeviceHandle='%s'\n", HandleToString(loaded->DeviceHandle)); 30 printf("Img FilePath='%s'\n", DevicePathToStr(loaded->FilePath)); 31 printf("Img Base=%lx Size=%lx\n", loaded->ImageBase, loaded->ImageSize); 32#endif 33 34 efi_simple_file_system_protocol* sfs; 35 r = xefi_open_protocol(loaded->DeviceHandle, &SimpleFileSystemProtocol, (void**)&sfs); 36 if (r) { 37 xprintf("LoadFile: Cannot open SimpleFileSystemProtocol (%s)\n", xefi_strerror(r)); 38 goto exit1; 39 } 40 41 efi_file_protocol* root; 42 r = sfs->OpenVolume(sfs, &root); 43 if (r) { 44 xprintf("LoadFile: Cannot open root volume (%s)\n", xefi_strerror(r)); 45 goto exit2; 46 } 47 48 r = root->Open(root, &file, filename, EFI_FILE_MODE_READ, 0); 49 if (r) { 50 xprintf("LoadFile: Cannot open file (%s)\n", xefi_strerror(r)); 51 goto exit3; 52 } 53 54exit3: 55 root->Close(root); 56exit2: 57 xefi_close_protocol(loaded->DeviceHandle, &SimpleFileSystemProtocol); 58exit1: 59 xefi_close_protocol(gImg, &LoadedImageProtocol); 60exit0: 61 return file; 62} 63 64void* xefi_read_file(efi_file_protocol* file, size_t* _sz, size_t front_bytes) { 65 efi_status r; 66 size_t pages = 0; 67 void* data = NULL; 68 69 char buf[512]; 70 size_t sz = sizeof(buf); 71 efi_file_info* finfo = (void*)buf; 72 r = file->GetInfo(file, &FileInfoGuid, &sz, finfo); 73 if (r) { 74 xprintf("LoadFile: Cannot get FileInfo (%s)\n", xefi_strerror(r)); 75 return NULL; 76 } 77 78 pages = (finfo->FileSize + front_bytes + 4095) / 4096; 79 r = gBS->AllocatePages(AllocateAnyPages, EfiLoaderData, pages, (efi_physical_addr *)&data); 80 if (r) { 81 xprintf("LoadFile: Cannot allocate buffer (%s)\n", xefi_strerror(r)); 82 return NULL; 83 } 84 85 sz = finfo->FileSize; 86 r = file->Read(file, &sz, data + front_bytes); 87 if (r) { 88 xprintf("LoadFile: Error reading file (%s)\n", xefi_strerror(r)); 89 gBS->FreePages((efi_physical_addr)data, pages); 90 return NULL; 91 } 92 if (sz != finfo->FileSize) { 93 xprintf("LoadFile: Short read\n"); 94 gBS->FreePages((efi_physical_addr)data, pages); 95 return NULL; 96 } 97 *_sz = finfo->FileSize; 98 99 return data + front_bytes; 100} 101 102void* xefi_load_file(char16_t* filename, size_t* _sz, size_t front_bytes) { 103 efi_file_protocol* file = xefi_open_file(filename); 104 if (!file) { 105 return NULL; 106 } 107 void* data = xefi_read_file(file, _sz, front_bytes); 108 file->Close(file); 109 return data; 110} 111