1818#include " uefi/uefi.h"
1919
2020#include < lib/bio.h>
21+ #include < lib/fs.h>
2122#include < lib/heap.h>
2223#include < lk/console_cmd.h>
2324#include < lk/debug.h>
@@ -68,7 +69,57 @@ void fill(T *data, size_t skip, uint8_t begin = 0) {
6869
6970static char16_t firmwareVendor[] = u" Little Kernel" ;
7071
71- int load_sections_and_execute (bdev_t *dev,
72+ class ImageReader {
73+ public:
74+ virtual ssize_t read (char *buf, off_t offset, size_t len) = 0;
75+ virtual void get_name (char *buf, size_t buf_size) = 0;
76+ };
77+
78+ class ImageReaderBdev final : public ImageReader {
79+ private:
80+ bdev_t *dev;
81+
82+ public:
83+ ImageReaderBdev (bdev_t *dev1): dev(dev1) {}
84+
85+ ssize_t read (char *buf, off_t offset, size_t len) {
86+ return bio_read (dev, static_cast <void *>(buf), offset, len);
87+ }
88+
89+ void get_name (char *buf, size_t buf_size) {
90+ if (buf_size <= 0 ) {
91+ return ;
92+ }
93+ strncpy (buf, dev->name , buf_size - 1 );
94+ }
95+ };
96+
97+ class ImageReaderFilehandle final : public ImageReader {
98+ private:
99+ filehandle *file_handle;
100+ const char *path;
101+
102+ public:
103+ ImageReaderFilehandle (filehandle *file_handle1, const char *path1): file_handle(file_handle1), path(path1) {}
104+
105+ ssize_t read (char *buf, off_t offset, size_t len) {
106+ return fs_read_file (file_handle, buf, offset, len);
107+ }
108+
109+ void get_name (char *buf, size_t buf_size) {
110+ if (buf_size <= 0 ) {
111+ return ;
112+ }
113+ strncpy (buf, path, buf_size);
114+ for (size_t i = 0 ; i < buf_size && buf[i]; i++) {
115+ if (buf[i] == ' /' ) {
116+ buf[i] = ' \\ ' ;
117+ }
118+ }
119+ }
120+ };
121+
122+ int load_sections_and_execute (ImageReader *reader,
72123 const IMAGE_NT_HEADERS64 *pe_header) {
73124 const auto file_header = &pe_header->FileHeader ;
74125 const auto optional_header = &pe_header->OptionalHeader ;
@@ -100,12 +151,13 @@ int load_sections_and_execute(bdev_t *dev,
100151 }
101152 memset (image_base, 0 , virtual_size);
102153 DEFER { free_pages (image_base, virtual_size / PAGE_SIZE); };
103- bio_read (dev, image_base, 0 , section_header[0 ].PointerToRawData );
154+ reader-> read ( image_base, 0 , section_header[0 ].PointerToRawData );
104155
105156 for (size_t i = 0 ; i < sections; i++) {
106157 const auto §ion = section_header[i];
107- bio_read (dev, image_base + section.VirtualAddress , section.PointerToRawData ,
108- section.SizeOfRawData );
158+ reader->read (image_base + section.VirtualAddress ,
159+ section.PointerToRawData ,
160+ section.SizeOfRawData );
109161 }
110162 printf (" Relocating image from 0x%llx to %p\n " , optional_header->ImageBase ,
111163 image_base);
@@ -145,7 +197,9 @@ int load_sections_and_execute(bdev_t *dev,
145197 printf (" efi_initialize_system_table_pointer failed: %lu\n " , status);
146198 return -static_cast <int >(status);
147199 }
148- setup_debug_support (table, image_base, virtual_size, dev);
200+ char path[FS_MAX_PATH_LEN];
201+ reader->get_name (path, sizeof (path));
202+ setup_debug_support (table, image_base, virtual_size, path);
149203
150204 constexpr size_t kStackSize = 1 * 1024ul * 1024 ;
151205 auto stack = reinterpret_cast <char *>(alloc_page (kStackSize , 23 ));
@@ -168,7 +222,11 @@ int cmd_uefi_load(int argc, const console_cmd_args *argv) {
168222 printf (" Usage: %s <name of block device to load from>\n " , argv[0 ].str );
169223 return 1 ;
170224 }
171- load_pe_file (argv[1 ].str );
225+ if (argv[1 ].str [0 ] == ' /' ) {
226+ load_pe_fs (argv[1 ].str );
227+ } else {
228+ load_pe_blockdev (argv[1 ].str );
229+ }
172230 return 0 ;
173231}
174232
@@ -201,21 +259,12 @@ STATIC_COMMAND_END(uefi);
201259
202260} // namespace
203261
204- int load_pe_file (const char *blkdev) {
205- bdev_t *dev = bio_open (blkdev);
206- if (!dev) {
207- printf (" error opening block device %s\n " , blkdev);
208- return -1 ;
209- }
210- DEFER {
211- bio_close (dev);
212- dev = nullptr ;
213- };
262+ int load_pe_file (ImageReader *reader) {
214263 constexpr size_t kBlocKSize = 4096 ;
215264
216265 lk_time_t t = current_time ();
217266 uint8_t *address = static_cast <uint8_t *>(malloc (kBlocKSize ));
218- ssize_t err = bio_read (dev, static_cast < void *>(address), 0 , kBlocKSize );
267+ ssize_t err = reader-> read ( reinterpret_cast < char *>(address), 0 , kBlocKSize );
219268 t = current_time () - t;
220269 dprintf (INFO, " bio_read returns %d, took %u msecs (%d bytes/sec)\n " , (int )err,
221270 (uint)t, (uint32_t )((uint64_t )err * 1000 / t));
@@ -253,7 +302,45 @@ int load_pe_file(const char *blkdev) {
253302 ToString (optional_header->Subsystem ));
254303 }
255304 printf (" Valid UEFI application found.\n " );
256- auto ret = load_sections_and_execute (dev , pe_header);
305+ auto ret = load_sections_and_execute (reader , pe_header);
257306 printf (" UEFI Application return code: %d\n " , ret);
258307 return ret;
259308}
309+
310+ int load_pe_blockdev (const char *blkdev) {
311+ bdev_t *dev = bio_open (blkdev);
312+
313+ if (!dev) {
314+ printf (" error opening block device %s\n " , blkdev);
315+ return -1 ;
316+ }
317+
318+ DEFER {
319+ bio_close (dev);
320+ dev = nullptr ;
321+ };
322+
323+ ImageReaderBdev reader (dev);
324+
325+ return load_pe_file (&reader);
326+ }
327+
328+ int load_pe_fs (const char *path) {
329+ filehandle *file_handle = nullptr ;
330+
331+ status_t status = fs_open_file (path, &file_handle);
332+ if (status < 0 ) {
333+ printf (" error opening file %s\n " , path);
334+ return -1 ;
335+ }
336+
337+ DEFER {
338+ fs_close_file (file_handle);
339+ file_handle = nullptr ;
340+ };
341+
342+ ImageReaderFilehandle reader (file_handle, path);
343+
344+ return load_pe_file (&reader);
345+
346+ }
0 commit comments