]> code.delx.au - refind/blob - mok/simple_file.c
Properly initialise variable to fix detection of non-Arch kernel versions
[refind] / mok / simple_file.c
1 /*
2 * Copyright 2012 <James.Bottomley@HansenPartnership.com>
3 *
4 * see COPYING file
5 */
6
7 #include <global.h>
8 #include "../include/refit_call_wrapper.h"
9
10 #include "simple_file.h"
11 //#include "execute.h" /* for generate_path() */
12
13 static EFI_GUID IMAGE_PROTOCOL = LOADED_IMAGE_PROTOCOL;
14 static EFI_GUID SIMPLE_FS_PROTOCOL = SIMPLE_FILE_SYSTEM_PROTOCOL;
15 static EFI_GUID FILE_INFO = EFI_FILE_INFO_ID;
16
17 EFI_STATUS
18 simple_file_open_by_handle(EFI_HANDLE device, CHAR16 *name, EFI_FILE **file, UINT64 mode)
19 {
20 EFI_STATUS efi_status;
21 EFI_FILE_IO_INTERFACE *drive;
22 EFI_FILE *root;
23
24 efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, device,
25 &SIMPLE_FS_PROTOCOL, (VOID**) &drive);
26
27 if (efi_status != EFI_SUCCESS) {
28 Print(L"Unable to find simple file protocol\n");
29 goto error;
30 }
31
32 efi_status = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root);
33
34 if (efi_status != EFI_SUCCESS) {
35 Print(L"Failed to open drive volume\n");
36 goto error;
37 }
38
39 efi_status = uefi_call_wrapper(root->Open, 5, root, file, name,
40 mode, 0);
41
42 error:
43 return efi_status;
44 }
45
46 // generate_path() from shim by Matthew J. Garrett
47 static
48 EFI_STATUS
49 generate_path(CHAR16* name, EFI_LOADED_IMAGE *li, EFI_DEVICE_PATH **path, CHAR16 **PathName)
50 {
51 unsigned int pathlen;
52 EFI_STATUS efi_status = EFI_SUCCESS;
53 CHAR16 *devpathstr = DevicePathToStr(li->FilePath),
54 *found = NULL;
55 int i;
56
57 for (i = 0; i < StrLen(devpathstr); i++) {
58 if (devpathstr[i] == '/')
59 devpathstr[i] = '\\';
60 if (devpathstr[i] == '\\')
61 found = &devpathstr[i];
62 }
63 if (!found) {
64 pathlen = 0;
65 } else {
66 while (*(found - 1) == '\\')
67 --found;
68 *found = '\0';
69 pathlen = StrLen(devpathstr);
70 }
71
72 if (name[0] != '\\')
73 pathlen++;
74
75 *PathName = AllocatePool((pathlen + 1 + StrLen(name))*sizeof(CHAR16));
76
77 if (!*PathName) {
78 Print(L"Failed to allocate path buffer\n");
79 efi_status = EFI_OUT_OF_RESOURCES;
80 goto error;
81 }
82
83 StrCpy(*PathName, devpathstr);
84
85 if (name[0] != '\\')
86 StrCat(*PathName, L"\\");
87 StrCat(*PathName, name);
88
89 *path = FileDevicePath(li->DeviceHandle, *PathName);
90
91 error:
92 FreePool(devpathstr);
93
94 return efi_status;
95 } // generate_path()
96
97 EFI_STATUS
98 simple_file_open(EFI_HANDLE image, CHAR16 *name, EFI_FILE **file, UINT64 mode)
99 {
100 EFI_STATUS efi_status;
101 EFI_HANDLE device;
102 EFI_LOADED_IMAGE *li;
103 EFI_DEVICE_PATH *loadpath = NULL;
104 CHAR16 *PathName = NULL;
105
106 efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image,
107 &IMAGE_PROTOCOL, (VOID**) &li);
108
109 if (efi_status != EFI_SUCCESS)
110 return simple_file_open_by_handle(image, name, file, mode);
111
112 efi_status = generate_path(name, li, &loadpath, &PathName);
113
114 if (efi_status != EFI_SUCCESS) {
115 Print(L"Unable to generate load path for %s\n", name);
116 return efi_status;
117 }
118
119 device = li->DeviceHandle;
120
121 efi_status = simple_file_open_by_handle(device, PathName, file, mode);
122
123 FreePool(PathName);
124 FreePool(loadpath);
125
126 return efi_status;
127 }
128
129 EFI_STATUS
130 simple_file_read_all(EFI_FILE *file, UINTN *size, void **buffer)
131 {
132 EFI_STATUS efi_status;
133 EFI_FILE_INFO *fi;
134 char buf[1024];
135
136 *size = sizeof(buf);
137 fi = (void *)buf;
138
139
140 efi_status = uefi_call_wrapper(file->GetInfo, 4, file, &FILE_INFO,
141 size, fi);
142 if (efi_status != EFI_SUCCESS) {
143 Print(L"Failed to get file info\n");
144 return efi_status;
145 }
146
147 *size = fi->FileSize;
148
149 *buffer = AllocatePool(*size);
150 if (!*buffer) {
151 Print(L"Failed to allocate buffer of size %d\n", *size);
152 return EFI_OUT_OF_RESOURCES;
153 }
154 efi_status = uefi_call_wrapper(file->Read, 3, file, size, *buffer);
155
156 return efi_status;
157 }
158
159 void
160 simple_file_close(EFI_FILE *file)
161 {
162 uefi_call_wrapper(file->Close, 1, file);
163 }