PatchworkOS
Loading...
Searching...
No Matches
disk.c
Go to the documentation of this file.
1#include "disk.h"
2
3#include "efilib.h"
4
5#include <boot/boot_info.h>
6
7#include <sys/list.h>
8
10{
11 if (file != NULL)
12 {
13 if (file->data != NULL)
14 {
15 FreePool(file->data);
16 }
17 FreePool(file);
18 }
19}
20
21static void boot_dir_free(boot_dir_t* dir)
22{
23 if (dir == NULL)
24 {
25 return;
26 }
27
28 while (!list_is_empty(&dir->children))
29 {
30 list_entry_t* entry = list_pop(&dir->children);
31 boot_dir_t* child = CONTAINER_OF(entry, boot_dir_t, entry);
32 boot_dir_free(child);
33 }
34
35 while (!list_is_empty(&dir->files))
36 {
37 list_entry_t* entry = list_pop(&dir->files);
38 boot_file_t* file = CONTAINER_OF(entry, boot_file_t, entry);
40 }
41
42 FreePool(dir);
43}
44
45static boot_file_t* ram_disk_load_file(EFI_FILE* volume, const CHAR16* path)
46{
47 if (volume == NULL || path == NULL)
48 {
49 return NULL;
50 }
51
52 EFI_FILE* efiFile;
53 EFI_STATUS status = uefi_call_wrapper(volume->Open, 5, volume, &efiFile, path, EFI_FILE_MODE_READ,
54 EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
55 if (EFI_ERROR(status))
56 {
57 return NULL;
58 }
59
60 boot_file_t* file = AllocatePool(sizeof(boot_file_t));
61 if (file == NULL)
62 {
63 uefi_call_wrapper(efiFile->Close, 1, efiFile);
64 return NULL;
65 }
66
67 list_entry_init(&file->entry);
68 SetMem(file->name, MAX_NAME, 0);
69 for (size_t i = 0; i < MAX_NAME - 1 && path[i] != '\0'; i++)
70 {
71 file->name[i] = (char)path[i];
72 }
73 file->data = NULL;
74 file->size = 0;
75
76 EFI_FILE_INFO* fileInfo = LibFileInfo(efiFile);
77 if (fileInfo == NULL)
78 {
80 uefi_call_wrapper(efiFile->Close, 1, efiFile);
81 return NULL;
82 }
83
84 file->size = fileInfo->FileSize;
85 FreePool(fileInfo);
86
87 if (file->size > 0)
88 {
89 file->data = AllocatePool(file->size);
90 if (file->data == NULL)
91 {
93 uefi_call_wrapper(efiFile->Close, 1, efiFile);
94 return NULL;
95 }
96
97 status = uefi_call_wrapper(efiFile->Read, 3, efiFile, &file->size, file->data);
98 if (EFI_ERROR(status))
99 {
101 uefi_call_wrapper(efiFile->Close, 1, efiFile);
102 return NULL;
103 }
104 }
105
106 uefi_call_wrapper(efiFile->Close, 1, efiFile);
107 return file;
108}
109
110static boot_dir_t* disk_load_dir(EFI_FILE* volume, const CHAR16* name)
111{
112 if (volume == NULL || name == NULL)
113 {
114 return NULL;
115 }
116
117 boot_dir_t* dir = AllocatePool(sizeof(boot_dir_t));
118 if (dir == NULL)
119 {
120 return NULL;
121 }
122
123 list_entry_init(&dir->entry);
124 SetMem(dir->name, MAX_NAME, 0);
125 for (size_t i = 0; i < MAX_NAME - 1 && name[i] != '\0'; i++)
126 {
127 dir->name[i] = (char)name[i];
128 }
129 list_init(&dir->children);
130 list_init(&dir->files);
131
132 while (1)
133 {
134 EFI_FILE_INFO* fileInfo;
135 UINTN fileInfoSize = 0;
136
137 EFI_STATUS status = uefi_call_wrapper(volume->Read, 3, volume, &fileInfoSize, NULL);
138 if (status != EFI_BUFFER_TOO_SMALL)
139 {
140 break;
141 }
142
143 fileInfo = AllocatePool(fileInfoSize);
144 if (fileInfo == NULL)
145 {
146 boot_dir_free(dir);
147 return NULL;
148 }
149
150 status = uefi_call_wrapper(volume->Read, 3, volume, &fileInfoSize, fileInfo);
151 if (EFI_ERROR(status))
152 {
153 FreePool(fileInfo);
154 boot_dir_free(dir);
155 return NULL;
156 }
157
158 if (fileInfo->Attribute & EFI_FILE_DIRECTORY)
159 {
160 if (StrCmp(fileInfo->FileName, L".") != 0 && StrCmp(fileInfo->FileName, L"..") != 0)
161 {
162 EFI_FILE* childVolume;
163 status = uefi_call_wrapper(volume->Open, 5, volume, &childVolume, fileInfo->FileName,
164 EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
165 if (EFI_ERROR(status))
166 {
167 FreePool(fileInfo);
168 boot_dir_free(dir);
169 return NULL;
170 }
171
172 boot_dir_t* child = disk_load_dir(childVolume, fileInfo->FileName);
173 uefi_call_wrapper(childVolume->Close, 1, childVolume);
174
175 if (child == NULL)
176 {
177 FreePool(fileInfo);
178 boot_dir_free(dir);
179 return NULL;
180 }
181
182 list_push(&dir->children, &child->entry);
183 }
184 }
185 else
186 {
187 boot_file_t* file = ram_disk_load_file(volume, fileInfo->FileName);
188 if (file == NULL)
189 {
190 FreePool(fileInfo);
191 boot_dir_free(dir);
192 return NULL;
193 }
194 list_push(&dir->files, &file->entry);
195 }
196
197 FreePool(fileInfo);
198 }
199
200 return dir;
201}
202
203EFI_STATUS disk_load(boot_disk_t* disk, EFI_FILE* rootHandle)
204{
205 if (disk == NULL)
206 {
207 return EFI_INVALID_PARAMETER;
208 }
209
210 Print(L"Loading disk... ");
211
212 disk->root = disk_load_dir(rootHandle, L"root");
213 if (disk->root == NULL)
214 {
215 Print(L"failed to load root directory!\n");
216 return EFI_LOAD_ERROR;
217 }
218
219 Print(L"done!\n");
220 return EFI_SUCCESS;
221}
#define MAX_NAME
Maximum length of names.
Definition MAX_NAME.h:11
static boot_file_t * ram_disk_load_file(EFI_FILE *volume, const CHAR16 *path)
Definition disk.c:45
EFI_STATUS disk_load(boot_disk_t *disk, EFI_FILE *rootHandle)
Definition disk.c:203
static boot_dir_t * disk_load_dir(EFI_FILE *volume, const CHAR16 *name)
Definition disk.c:110
static void boot_dir_free(boot_dir_t *dir)
Definition disk.c:21
static void boot_file_free(boot_file_t *file)
Definition disk.c:9
static void list_push(list_t *list, list_entry_t *entry)
Pushes an entry to the end of the list.
Definition list.h:345
static bool list_is_empty(list_t *list)
Checks if a list is empty.
Definition list.h:229
static void list_entry_init(list_entry_t *entry)
Initializes a list entry.
Definition list.h:184
static void list_init(list_t *list)
Initializes a list.
Definition list.h:198
static list_entry_t * list_pop(list_t *list)
Pops the first entry from the list.
Definition list.h:361
#define NULL
Pointer error value.
Definition NULL.h:23
#define CONTAINER_OF(ptr, type, member)
Container of macro.
static dentry_t * file
Definition log_file.c:17
list_t files
Definition boot_info.h:68
list_t children
Definition boot_info.h:67
list_entry_t entry
Definition boot_info.h:65
char name[MAX_NAME]
Definition boot_info.h:66
boot_dir_t * root
Definition boot_info.h:73
char name[MAX_NAME]
Definition dentry.h:86
A entry in a doubly linked list.
Definition list.h:38