blob: 844d08246ee3367192dfad9d2b5eff5e64e444bd [file] [log] [blame]
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
4 *
5 * dtbdump.efi saves the device tree provided as a configuration table
6 * to a file.
7 */
8
9#include <common.h>
10#include <efi_api.h>
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +010011#include <efi_dt_fixup.h>
Simon Glass401d1c42020-10-30 21:38:53 -060012#include <linux/libfdt.h>
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +010013
14#define BUFFER_SIZE 64
15#define ESC 0x17
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +010016
17#define efi_size_in_pages(size) ((size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT)
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +010018
19static struct efi_simple_text_output_protocol *cerr;
20static struct efi_simple_text_output_protocol *cout;
21static struct efi_simple_text_input_protocol *cin;
22static struct efi_boot_services *bs;
23static const efi_guid_t fdt_guid = EFI_FDT_GUID;
24static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
25static const efi_guid_t guid_simple_file_system_protocol =
26 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +010027static efi_handle_t handle;
28static struct efi_system_table *systable;
29static const efi_guid_t efi_dt_fixup_protocol_guid = EFI_DT_FIXUP_PROTOCOL_GUID;
30static const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID;
31
32/**
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +010033 * print() - print string
34 *
35 * @string: text
36 */
37static void print(u16 *string)
38{
39 cout->output_string(cout, string);
40}
41
42/**
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +010043 * error() - print error string
44 *
45 * @string: error text
46 */
47static void error(u16 *string)
48{
49 cout->set_attribute(cout, EFI_LIGHTRED | EFI_BACKGROUND_BLACK);
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +010050 print(string);
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +010051 cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
52}
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +010053
54/**
Heinrich Schuchardtb6f60802021-01-17 05:13:21 +010055 * efi_input_yn() - get answer to yes/no question
56 *
57 * Return:
58 * y or Y
59 * EFI_SUCCESS
60 * n or N
61 * EFI_ACCESS_DENIED
62 * ESC
63 * EFI_ABORTED
64 */
65static efi_status_t efi_input_yn(void)
66{
67 struct efi_input_key key = {0};
68 efi_uintn_t index;
69 efi_status_t ret;
70
71 /* Drain the console input */
72 ret = cin->reset(cin, true);
73 for (;;) {
74 ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
75 if (ret != EFI_SUCCESS)
76 continue;
77 ret = cin->read_key_stroke(cin, &key);
78 if (ret != EFI_SUCCESS)
79 continue;
80 switch (key.scan_code) {
81 case 0x17: /* Escape */
82 return EFI_ABORTED;
83 default:
84 break;
85 }
86 /* Convert to lower case */
87 switch (key.unicode_char | 0x20) {
88 case 'y':
89 return EFI_SUCCESS;
90 case 'n':
91 return EFI_ACCESS_DENIED;
92 default:
93 break;
94 }
95 }
96}
97
98/**
99 * efi_input() - read string from console
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100100 *
101 * @buffer: input buffer
102 * @buffer_size: buffer size
103 * Return: status code
104 */
105static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
106{
107 struct efi_input_key key = {0};
108 efi_uintn_t index;
109 efi_uintn_t pos = 0;
110 u16 outbuf[2] = L" ";
111 efi_status_t ret;
112
113 /* Drain the console input */
114 ret = cin->reset(cin, true);
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100115 *buffer = 0;
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100116 for (;;) {
117 ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
118 if (ret != EFI_SUCCESS)
119 continue;
120 ret = cin->read_key_stroke(cin, &key);
121 if (ret != EFI_SUCCESS)
122 continue;
123 switch (key.scan_code) {
124 case 0x17: /* Escape */
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100125 print(L"\r\nAborted\r\n");
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100126 return EFI_ABORTED;
127 default:
128 break;
129 }
130 switch (key.unicode_char) {
131 case 0x08: /* Backspace */
132 if (pos) {
133 buffer[pos--] = 0;
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100134 print(L"\b \b");
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100135 }
136 break;
137 case 0x0a: /* Linefeed */
138 case 0x0d: /* Carriage return */
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100139 print(L"\r\n");
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100140 return EFI_SUCCESS;
141 default:
142 break;
143 }
144 /* Ignore surrogate codes */
145 if (key.unicode_char >= 0xD800 && key.unicode_char <= 0xDBFF)
146 continue;
147 if (key.unicode_char >= 0x20 &&
148 pos < buffer_size - 1) {
149 *outbuf = key.unicode_char;
150 buffer[pos++] = key.unicode_char;
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100151 buffer[pos] = 0;
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100152 print(outbuf);
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100153 }
154 }
155}
156
157/*
158 * Convert FDT value to host endianness.
159 *
160 * @val FDT value
161 * @return converted value
162 */
163static u32 f2h(fdt32_t val)
164{
165 char *buf = (char *)&val;
166 char i;
167
168 /* Swap the bytes */
169 i = buf[0]; buf[0] = buf[3]; buf[3] = i;
170 i = buf[1]; buf[1] = buf[2]; buf[2] = i;
171 return *(u32 *)buf;
172}
173
174/**
175 * get_dtb() - get device tree
176 *
177 * @systable: system table
178 * Return: device tree or NULL
179 */
180void *get_dtb(struct efi_system_table *systable)
181{
182 void *dtb = NULL;
183 efi_uintn_t i;
184
185 for (i = 0; i < systable->nr_tables; ++i) {
186 if (!memcmp(&systable->tables[i].guid, &fdt_guid,
187 sizeof(efi_guid_t))) {
188 dtb = systable->tables[i].table;
189 break;
190 }
191 }
192 return dtb;
193}
194
195/**
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100196 * skip_whitespace() - skip over leading whitespace
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100197 *
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100198 * @pos: UTF-16 string
199 * Return: pointer to first non-whitespace
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100200 */
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100201u16 *skip_whitespace(u16 *pos)
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100202{
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100203 for (; *pos && *pos <= 0x20; ++pos)
204 ;
205 return pos;
206}
207
208/**
209 * starts_with() - check if @string starts with @keyword
210 *
211 * @string: string to search for keyword
212 * @keyword: keyword to be searched
213 * Return: true fi @string starts with the keyword
214 */
215bool starts_with(u16 *string, u16 *keyword)
216{
217 for (; *keyword; ++string, ++keyword) {
218 if (*string != *keyword)
219 return false;
220 }
221 return true;
222}
223
224/**
225 * do_help() - print help
226 */
227void do_help(void)
228{
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100229 error(L"load <dtb> - load device-tree from file\r\n");
230 error(L"save <dtb> - save device-tree to file\r\n");
231 error(L"exit - exit the shell\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100232}
233
234/**
235 * do_load() - load and install device-tree
236 *
237 * @filename: file name
238 * Return: status code
239 */
240efi_status_t do_load(u16 *filename)
241{
242 struct efi_dt_fixup_protocol *dt_fixup_prot;
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100243 struct efi_loaded_image *loaded_image;
244 struct efi_simple_file_system_protocol *file_system;
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100245 struct efi_file_handle *root = NULL, *file = NULL;
246 u64 addr = 0;
247 struct efi_file_info *info;
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100248 struct fdt_header *dtb;
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100249 efi_uintn_t buffer_size;
250 efi_uintn_t pages;
251 efi_status_t ret, ret2;
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100252
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100253 ret = bs->locate_protocol(&efi_dt_fixup_protocol_guid, NULL,
254 (void **)&dt_fixup_prot);
255 if (ret != EFI_SUCCESS) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100256 error(L"Device-tree fix-up protocol not found\r\n");
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100257 return ret;
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100258 }
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100259
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100260 filename = skip_whitespace(filename);
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100261
262 ret = bs->open_protocol(handle, &loaded_image_guid,
263 (void **)&loaded_image, NULL, NULL,
264 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
265 if (ret != EFI_SUCCESS) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100266 error(L"Loaded image protocol not found\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100267 return ret;
268 }
269 /* Open the simple file system protocol */
270 ret = bs->open_protocol(loaded_image->device_handle,
271 &guid_simple_file_system_protocol,
272 (void **)&file_system, NULL, NULL,
273 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
274 if (ret != EFI_SUCCESS) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100275 error(L"Failed to open simple file system protocol\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100276 goto out;
277 }
278
279 /* Open volume */
280 ret = file_system->open_volume(file_system, &root);
281 if (ret != EFI_SUCCESS) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100282 error(L"Failed to open volume\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100283 goto out;
284 }
285
286 /* Open file */
287 ret = root->open(root, &file, filename, EFI_FILE_MODE_READ, 0);
288 if (ret != EFI_SUCCESS) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100289 error(L"File not found\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100290 goto out;
291 }
292 /* Get file size */
293 buffer_size = 0;
294 ret = file->getinfo(file, &efi_file_info_guid, &buffer_size, NULL);
295 if (ret != EFI_BUFFER_TOO_SMALL) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100296 error(L"Can't get file info size\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100297 goto out;
298 }
299 ret = bs->allocate_pool(EFI_LOADER_DATA, buffer_size, (void **)&info);
300 if (ret != EFI_SUCCESS) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100301 error(L"Out of memory\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100302 goto out;
303 }
304 ret = file->getinfo(file, &efi_file_info_guid, &buffer_size, info);
305 if (ret != EFI_SUCCESS) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100306 error(L"Can't get file info\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100307 goto out;
308 }
309 buffer_size = info->file_size;
310 pages = efi_size_in_pages(buffer_size);
311 ret = bs->free_pool(info);
312 if (ret != EFI_SUCCESS)
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100313 error(L"Can't free memory pool\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100314 /* Read file */
315 ret = bs->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
316 EFI_ACPI_RECLAIM_MEMORY,
317 pages, &addr);
318 if (ret != EFI_SUCCESS) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100319 error(L"Out of memory\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100320 goto out;
321 }
322 dtb = (struct fdt_header *)(uintptr_t)addr;
323 ret = file->read(file, &buffer_size, dtb);
324 if (ret != EFI_SUCCESS) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100325 error(L"Can't read file\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100326 goto out;
327 }
328 /* Fixup file, expecting EFI_BUFFER_TOO_SMALL */
329 ret = dt_fixup_prot->fixup(dt_fixup_prot, dtb, &buffer_size,
330 EFI_DT_APPLY_FIXUPS | EFI_DT_RESERVE_MEMORY |
331 EFI_DT_INSTALL_TABLE);
332 if (ret == EFI_BUFFER_TOO_SMALL) {
333 /* Read file into larger buffer */
334 ret = bs->free_pages(addr, pages);
335 if (ret != EFI_SUCCESS)
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100336 error(L"Can't free memory pages\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100337 pages = efi_size_in_pages(buffer_size);
338 ret = bs->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
339 EFI_ACPI_RECLAIM_MEMORY,
340 pages, &addr);
341 if (ret != EFI_SUCCESS) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100342 error(L"Out of memory\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100343 goto out;
344 }
345 dtb = (struct fdt_header *)(uintptr_t)addr;
346 ret = file->setpos(file, 0);
347 if (ret != EFI_SUCCESS) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100348 error(L"Can't position file\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100349 goto out;
350 }
351 ret = file->read(file, &buffer_size, dtb);
352 if (ret != EFI_SUCCESS) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100353 error(L"Can't read file\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100354 goto out;
355 }
356 buffer_size = pages << EFI_PAGE_SHIFT;
357 ret = dt_fixup_prot->fixup(
358 dt_fixup_prot, dtb, &buffer_size,
359 EFI_DT_APPLY_FIXUPS | EFI_DT_RESERVE_MEMORY |
360 EFI_DT_INSTALL_TABLE);
361 }
362 if (ret == EFI_SUCCESS)
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100363 print(L"device-tree installed\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100364 else
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100365 error(L"Device-tree fix-up failed\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100366out:
367 if (addr) {
368 ret2 = bs->free_pages(addr, pages);
369 if (ret2 != EFI_SUCCESS)
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100370 error(L"Can't free memory pages\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100371 }
372 if (file) {
373 ret2 = file->close(file);
374 if (ret2 != EFI_SUCCESS)
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100375 error(L"Can't close file\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100376 }
377 if (root) {
378 ret2 = root->close(root);
379 if (ret2 != EFI_SUCCESS)
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100380 error(L"Can't close volume\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100381 }
382 return ret;
383}
384
385/**
386 * do_save() - save current device-tree
387 *
388 * @filename: file name
389 * Return: status code
390 */
391efi_status_t do_save(u16 *filename)
392{
393 struct efi_loaded_image *loaded_image;
394 struct efi_simple_file_system_protocol *file_system;
395 efi_uintn_t dtb_size;
396 struct efi_file_handle *root, *file;
397 struct fdt_header *dtb;
398 efi_uintn_t ret;
399
400 dtb = get_dtb(systable);
401 if (!dtb) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100402 error(L"DTB not found\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100403 return EFI_NOT_FOUND;
404 }
405 if (f2h(dtb->magic) != FDT_MAGIC) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100406 error(L"Wrong device tree magic\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100407 return EFI_NOT_FOUND;
408 }
409 dtb_size = f2h(dtb->totalsize);
410
411 filename = skip_whitespace(filename);
412
413 ret = bs->open_protocol(handle, &loaded_image_guid,
414 (void **)&loaded_image, NULL, NULL,
415 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
416 if (ret != EFI_SUCCESS) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100417 error(L"Loaded image protocol not found\r\n");
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100418 return ret;
419 }
420
421 /* Open the simple file system protocol */
422 ret = bs->open_protocol(loaded_image->device_handle,
423 &guid_simple_file_system_protocol,
424 (void **)&file_system, NULL, NULL,
425 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
426 if (ret != EFI_SUCCESS) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100427 error(L"Failed to open simple file system protocol\r\n");
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100428 return ret;
429 }
430
431 /* Open volume */
432 ret = file_system->open_volume(file_system, &root);
433 if (ret != EFI_SUCCESS) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100434 error(L"Failed to open volume\r\n");
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100435 return ret;
436 }
Heinrich Schuchardtb6f60802021-01-17 05:13:21 +0100437 /* Check if file already exists */
438 ret = root->open(root, &file, filename, EFI_FILE_MODE_READ, 0);
439 if (ret == EFI_SUCCESS) {
440 file->close(file);
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100441 print(L"Overwrite existing file (y/n)? ");
Heinrich Schuchardtb6f60802021-01-17 05:13:21 +0100442 ret = efi_input_yn();
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100443 print(L"\r\n");
Heinrich Schuchardtb6f60802021-01-17 05:13:21 +0100444 if (ret != EFI_SUCCESS) {
445 root->close(root);
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100446 error(L"Aborted by user\r\n");
Heinrich Schuchardtb6f60802021-01-17 05:13:21 +0100447 return ret;
448 }
449 }
450
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100451 /* Create file */
452 ret = root->open(root, &file, filename,
453 EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
454 EFI_FILE_MODE_CREATE, EFI_FILE_ARCHIVE);
455 if (ret == EFI_SUCCESS) {
456 /* Write file */
457 ret = file->write(file, &dtb_size, dtb);
458 if (ret != EFI_SUCCESS)
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100459 error(L"Failed to write file\r\n");
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100460 file->close(file);
461 } else {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100462 error(L"Failed to open file\r\n");
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100463 }
464 root->close(root);
465
466 if (ret == EFI_SUCCESS) {
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100467 print(filename);
468 print(L" written\r\n");
Heinrich Schuchardtb1aa6fc2020-11-04 22:00:48 +0100469 }
470
471 return ret;
472}
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100473
474/**
475 * efi_main() - entry point of the EFI application.
476 *
477 * @handle: handle of the loaded image
478 * @systab: system table
479 * @return: status code
480 */
481efi_status_t EFIAPI efi_main(efi_handle_t image_handle,
482 struct efi_system_table *systab)
483{
484 handle = image_handle;
485 systable = systab;
486 cerr = systable->std_err;
487 cout = systable->con_out;
488 cin = systable->con_in;
489 bs = systable->boottime;
490
491 cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
492 cout->clear_screen(cout);
493 cout->set_attribute(cout, EFI_WHITE | EFI_BACKGROUND_BLACK);
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100494 print(L"DTB Dump\r\n========\r\n\r\n");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100495 cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
496
497 for (;;) {
498 u16 command[BUFFER_SIZE];
499 u16 *pos;
500 efi_uintn_t ret;
501
Heinrich Schuchardtd56013d2021-01-19 10:06:00 +0100502 print(L"=> ");
Heinrich Schuchardt8e70f1c2020-12-13 19:13:57 +0100503 ret = efi_input(command, sizeof(command));
504 if (ret == EFI_ABORTED)
505 break;
506 pos = skip_whitespace(command);
507 if (starts_with(pos, L"exit"))
508 break;
509 else if (starts_with(pos, L"load "))
510 do_load(pos + 5);
511 else if (starts_with(pos, L"save "))
512 do_save(pos + 5);
513 else
514 do_help();
515 }
516
517 cout->set_attribute(cout, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK);
518 cout->clear_screen(cout);
519 return EFI_SUCCESS;
520}