1 /******************************************************************************
2 *
3 * Module Name: oseficlib - EFI specific CLibrary interfaces
4 *
5 *****************************************************************************/
6
7 /******************************************************************************
8 *
9 * 1. Copyright Notice
10 *
11 * Some or all of this work - Copyright (c) 1999 - 2023, Intel Corp.
12 * All rights reserved.
13 *
14 * 2. License
15 *
16 * 2.1. This is your license from Intel Corp. under its intellectual property
17 * rights. You may have additional license terms from the party that provided
18 * you this software, covering your right to use that party's intellectual
19 * property rights.
20 *
21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22 * copy of the source code appearing in this file ("Covered Code") an
23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24 * base code distributed originally by Intel ("Original Intel Code") to copy,
25 * make derivatives, distribute, use and display any portion of the Covered
26 * Code in any form, with the right to sublicense such rights; and
27 *
28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29 * license (with the right to sublicense), under only those claims of Intel
30 * patents that are infringed by the Original Intel Code, to make, use, sell,
31 * offer to sell, and import the Covered Code and derivative works thereof
32 * solely to the minimum extent necessary to exercise the above copyright
33 * license, and in no event shall the patent license extend to any additions
34 * to or modifications of the Original Intel Code. No other license or right
35 * is granted directly or by implication, estoppel or otherwise;
36 *
37 * The above copyright and patent license is granted only if the following
38 * conditions are met:
39 *
40 * 3. Conditions
41 *
42 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43 * Redistribution of source code of any substantial portion of the Covered
44 * Code or modification with rights to further distribute source must include
45 * the above Copyright Notice, the above License, this list of Conditions,
46 * and the following Disclaimer and Export Compliance provision. In addition,
47 * Licensee must cause all Covered Code to which Licensee contributes to
48 * contain a file documenting the changes Licensee made to create that Covered
49 * Code and the date of any change. Licensee must include in that file the
50 * documentation of any changes made by any predecessor Licensee. Licensee
51 * must include a prominent statement that the modification is derived,
52 * directly or indirectly, from Original Intel Code.
53 *
54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55 * Redistribution of source code of any substantial portion of the Covered
56 * Code or modification without rights to further distribute source must
57 * include the following Disclaimer and Export Compliance provision in the
58 * documentation and/or other materials provided with distribution. In
59 * addition, Licensee may not authorize further sublicense of source of any
60 * portion of the Covered Code, and must include terms to the effect that the
61 * license from Licensee to its licensee is limited to the intellectual
62 * property embodied in the software Licensee provides to its licensee, and
63 * not to intellectual property embodied in modifications its licensee may
64 * make.
65 *
66 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67 * substantial portion of the Covered Code or modification must reproduce the
68 * above Copyright Notice, and the following Disclaimer and Export Compliance
69 * provision in the documentation and/or other materials provided with the
70 * distribution.
71 *
72 * 3.4. Intel retains all right, title, and interest in and to the Original
73 * Intel Code.
74 *
75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76 * Intel shall be used in advertising or otherwise to promote the sale, use or
77 * other dealings in products derived from or relating to the Covered Code
78 * without prior written authorization from Intel.
79 *
80 * 4. Disclaimer and Export Compliance
81 *
82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88 * PARTICULAR PURPOSE.
89 *
90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97 * LIMITED REMEDY.
98 *
99 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100 * software or system incorporating such software without first obtaining any
101 * required license or other approval from the U. S. Department of Commerce or
102 * any other agency or department of the United States Government. In the
103 * event Licensee exports any such software from the United States or
104 * re-exports any such software from a foreign destination, Licensee shall
105 * ensure that the distribution and export/re-export of the software is in
106 * compliance with all laws, regulations, orders, or other restrictions of the
107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108 * any of its subsidiaries will export/re-export any technical data, process,
109 * software, or service, directly or indirectly, to any country for which the
110 * United States government or any agency thereof requires an export license,
111 * other governmental approval, or letter of assurance, without first obtaining
112 * such license, approval or letter.
113 *
114 *****************************************************************************
115 *
116 * Alternatively, you may choose to be licensed under the terms of the
117 * following license:
118 *
119 * Redistribution and use in source and binary forms, with or without
120 * modification, are permitted provided that the following conditions
121 * are met:
122 * 1. Redistributions of source code must retain the above copyright
123 * notice, this list of conditions, and the following disclaimer,
124 * without modification.
125 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126 * substantially similar to the "NO WARRANTY" disclaimer below
127 * ("Disclaimer") and any redistribution must be conditioned upon
128 * including a substantially similar Disclaimer requirement for further
129 * binary redistribution.
130 * 3. Neither the names of the above-listed copyright holders nor the names
131 * of any contributors may be used to endorse or promote products derived
132 * from this software without specific prior written permission.
133 *
134 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145 *
146 * Alternatively, you may choose to be licensed under the terms of the
147 * GNU General Public License ("GPL") version 2 as published by the Free
148 * Software Foundation.
149 *
150 *****************************************************************************/
151
152 #include "acpi.h"
153 #include "accommon.h"
154 #include "acapps.h"
155
156 #define _COMPONENT ACPI_OS_SERVICES
157 ACPI_MODULE_NAME ("oseficlib")
158
159
160 /* Local definitions */
161
162 #define ACPI_EFI_PRINT_LENGTH 256
163
164 #define ACPI_EFI_KEY_ESC 0x0000
165 #define ACPI_EFI_KEY_BACKSPACE 0x0008
166 #define ACPI_EFI_KEY_ENTER 0x000D
167 #define ACPI_EFI_KEY_CTRL_C 0x0003
168
169 #define ACPI_EFI_ASCII_NULL 0x00
170 #define ACPI_EFI_ASCII_DEL 0x7F
171 #define ACPI_EFI_ASCII_ESC 0x1B
172 #define ACPI_EFI_ASCII_CR '\r'
173 #define ACPI_EFI_ASCII_NL '\n'
174
175
176 /* Local prototypes */
177
178 static int
179 AcpiEfiArgify (
180 char *String,
181 int *ArgcPtr,
182 char ***ArgvPtr);
183
184 static int
185 AcpiEfiConvertArgcv (
186 CHAR16 *LoadOpt,
187 UINT32 LoadOptSize,
188 int *ArgcPtr,
189 char ***ArgvPtr,
190 char **BufferPtr);
191
192 static int
193 AcpiEfiGetFileInfo (
194 FILE *File,
195 ACPI_EFI_FILE_INFO **InfoPtr);
196
197 static CHAR16 *
198 AcpiEfiFlushFile (
199 FILE *File,
200 CHAR16 *Begin,
201 CHAR16 *End,
202 CHAR16 *Pos,
203 BOOLEAN FlushAll);
204
205
206 /* Local variables */
207
208 FILE *stdin = NULL;
209 FILE *stdout = NULL;
210 FILE *stderr = NULL;
211 static ACPI_EFI_FILE_HANDLE AcpiGbl_EfiCurrentVolume = NULL;
212 ACPI_EFI_GUID AcpiGbl_LoadedImageProtocol = ACPI_EFI_LOADED_IMAGE_PROTOCOL;
213 ACPI_EFI_GUID AcpiGbl_TextInProtocol = ACPI_SIMPLE_TEXT_INPUT_PROTOCOL;
214 ACPI_EFI_GUID AcpiGbl_TextOutProtocol = ACPI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
215 ACPI_EFI_GUID AcpiGbl_FileSystemProtocol = ACPI_SIMPLE_FILE_SYSTEM_PROTOCOL;
216 ACPI_EFI_GUID AcpiGbl_GenericFileInfo = ACPI_EFI_FILE_INFO_ID;
217
218 int errno = 0;
219
220
221 /*******************************************************************************
222 *
223 * FUNCTION: fopen
224 *
225 * PARAMETERS: Path - File path
226 * Modes - File operation type
227 *
228 * RETURN: File descriptor
229 *
230 * DESCRIPTION: Open a file for reading or/and writing.
231 *
232 ******************************************************************************/
233
234 FILE *
fopen(const char * Path,const char * Modes)235 fopen (
236 const char *Path,
237 const char *Modes)
238 {
239 ACPI_EFI_STATUS EfiStatus = ACPI_EFI_SUCCESS;
240 UINT64 OpenModes;
241 ACPI_EFI_FILE_HANDLE EfiFile = NULL;
242 CHAR16 *Path16 = NULL;
243 CHAR16 *Pos16;
244 const char *Pos;
245 INTN Count, i;
246 BOOLEAN IsAppend = FALSE;
247 FILE *File = NULL;
248
249
250 if (!Path)
251 {
252 errno = EINVAL;
253 return (NULL);
254 }
255
256 /*
257 * Convert modes, EFI says the only 2 read/write modes are read-only,
258 * read+write. Thus set default mode as read-only.
259 */
260 OpenModes = ACPI_EFI_FILE_MODE_READ;
261 switch (*Modes++)
262 {
263 case 'r':
264
265 break;
266
267 case 'w':
268
269 OpenModes |= (ACPI_EFI_FILE_MODE_WRITE | ACPI_EFI_FILE_MODE_CREATE);
270 break;
271
272 case 'a':
273
274 OpenModes |= (ACPI_EFI_FILE_MODE_WRITE | ACPI_EFI_FILE_MODE_CREATE);
275 IsAppend = TRUE;
276 break;
277
278 default:
279
280 errno = EINVAL;
281 return (NULL);
282 }
283
284 for (; *Modes; Modes++)
285 {
286 switch (*Modes)
287 {
288 case '+':
289
290 OpenModes |= (ACPI_EFI_FILE_MODE_WRITE | ACPI_EFI_FILE_MODE_CREATE);
291 break;
292
293 case 'b':
294 case 't':
295
296 break;
297
298 case 'f':
299 default:
300
301 break;
302 }
303 }
304
305 /* Allocate path buffer */
306
307 Count = strlen (Path);
308 Path16 = ACPI_ALLOCATE_ZEROED ((Count + 1) * sizeof (CHAR16));
309 if (!Path16)
310 {
311 EfiStatus = ACPI_EFI_BAD_BUFFER_SIZE;
312 errno = ENOMEM;
313 goto ErrorExit;
314 }
315 Pos = Path;
316 Pos16 = Path16;
317 while (*Pos == '/' || *Pos == '\\')
318 {
319 Pos++;
320 Count--;
321 }
322 for (i = 0; i < Count; i++)
323 {
324 if (*Pos == '/')
325 {
326 *Pos16++ = '\\';
327 Pos++;
328 }
329 else
330 {
331 *Pos16++ = *Pos++;
332 }
333 }
334 *Pos16 = '\0';
335
336 EfiStatus = uefi_call_wrapper (AcpiGbl_EfiCurrentVolume->Open, 5,
337 AcpiGbl_EfiCurrentVolume, &EfiFile, Path16, OpenModes, 0);
338 if (ACPI_EFI_ERROR (EfiStatus))
339 {
340 fprintf (stderr, "EFI_FILE_HANDLE->Open() failure.\n");
341 errno = ENOENT;
342 goto ErrorExit;
343 }
344
345 File = (FILE *) EfiFile;
346 if (IsAppend)
347 {
348 fseek (File, 0, SEEK_END);
349 }
350
351 ErrorExit:
352
353 if (Path16)
354 {
355 ACPI_FREE (Path16);
356 }
357
358 return (File);
359 }
360
361
362 /*******************************************************************************
363 *
364 * FUNCTION: fclose
365 *
366 * PARAMETERS: File - File descriptor
367 *
368 * RETURN: None.
369 *
370 * DESCRIPTION: Close a file.
371 *
372 ******************************************************************************/
373
374 void
fclose(FILE * File)375 fclose (
376 FILE *File)
377 {
378 ACPI_EFI_FILE_HANDLE EfiFile;
379
380
381 if (File == stdin || File == stdout ||
382 File == stderr)
383 {
384 return;
385 }
386 EfiFile = (ACPI_EFI_FILE_HANDLE) File;
387 (void) uefi_call_wrapper (AcpiGbl_EfiCurrentVolume->Close, 1, EfiFile);
388
389 return;
390 }
391
392
393 /*******************************************************************************
394 *
395 * FUNCTION: fgetc
396 *
397 * PARAMETERS: File - File descriptor
398 *
399 * RETURN: The character read or EOF on the end of the file or error
400 *
401 * DESCRIPTION: Read a character from the file.
402 *
403 ******************************************************************************/
404
405 int
fgetc(FILE * File)406 fgetc (
407 FILE *File)
408 {
409 UINT8 Byte;
410 int Length;
411
412
413 Length = fread (ACPI_CAST_PTR (void, &Byte), 1, 1, File);
414 if (Length == 0)
415 {
416 Length = EOF;
417 }
418 else if (Length == 1)
419 {
420 Length = (int) Byte;
421 }
422
423 return (Length);
424 }
425
426
427 /*******************************************************************************
428 *
429 * FUNCTION: fputc
430 *
431 * PARAMETERS: File - File descriptor
432 * c - Character byte
433 *
434 * RETURN: The character written or EOF on the end of the file or error
435 *
436 * DESCRIPTION: Write a character to the file.
437 *
438 ******************************************************************************/
439
440 int
fputc(FILE * File,char c)441 fputc (
442 FILE *File,
443 char c)
444 {
445 UINT8 Byte = (UINT8) c;
446 int Length;
447
448
449 Length = fwrite (ACPI_CAST_PTR (void, &Byte), 1, 1, File);
450 if (Length == 0)
451 {
452 Length = EOF;
453 }
454 else if (Length == 1)
455 {
456 Length = (int) Byte;
457 }
458
459 return (Length);
460 }
461
462
463 /*******************************************************************************
464 *
465 * FUNCTION: fgets
466 *
467 * PARAMETERS: File - File descriptor
468 *
469 * RETURN: The string read
470 *
471 * DESCRIPTION: Read a string from the file.
472 *
473 ******************************************************************************/
474
475 char *
fgets(char * s,ACPI_SIZE Size,FILE * File)476 fgets (
477 char *s,
478 ACPI_SIZE Size,
479 FILE *File)
480 {
481 ACPI_SIZE ReadBytes = 0;
482 int Ret;
483
484
485 if (Size <= 1)
486 {
487 errno = EINVAL;
488 return (NULL);
489 }
490 while (ReadBytes < (Size - 1))
491 {
492 Ret = fgetc (File);
493 if (Ret == EOF)
494 {
495 if (ReadBytes == 0)
496 {
497 return (NULL);
498 }
499 break;
500 }
501 else if (Ret < 0)
502 {
503 errno = EIO;
504 return (NULL);
505 }
506 else if (Ret == '\n')
507 {
508 s[ReadBytes++] = (char) Ret;
509 break;
510 }
511 else
512 {
513 s[ReadBytes++] = (char) Ret;
514 }
515 }
516
517 s[ReadBytes] = '\0';
518 return (s);
519 }
520
521
522 /*******************************************************************************
523 *
524 * FUNCTION: fread
525 *
526 * PARAMETERS: Buffer - Data buffer
527 * Size - Data block size
528 * Count - Number of data blocks
529 * File - File descriptor
530 *
531 * RETURN: Size of successfully read buffer
532 *
533 * DESCRIPTION: Read from a file.
534 *
535 ******************************************************************************/
536
537 int
fread(void * Buffer,ACPI_SIZE Size,ACPI_SIZE Count,FILE * File)538 fread (
539 void *Buffer,
540 ACPI_SIZE Size,
541 ACPI_SIZE Count,
542 FILE *File)
543 {
544 int Length = -EINVAL;
545 ACPI_EFI_FILE_HANDLE EfiFile;
546 ACPI_SIMPLE_INPUT_INTERFACE *In;
547 UINTN ReadSize;
548 ACPI_EFI_STATUS EfiStatus;
549 ACPI_EFI_INPUT_KEY Key;
550 ACPI_SIZE Pos = 0;
551
552
553 if (!Buffer)
554 {
555 errno = EINVAL;
556 goto ErrorExit;
557 }
558
559 ReadSize = Size * Count;
560
561 if (File == stdout || File == stderr)
562 {
563 /* Do not support read operations on output console */
564 }
565 else if (File == stdin)
566 {
567 In = ACPI_CAST_PTR (ACPI_SIMPLE_INPUT_INTERFACE, File);
568
569 while (Pos < ReadSize)
570 {
571 WaitKey:
572 EfiStatus = uefi_call_wrapper (In->ReadKeyStroke, 2, In, &Key);
573 if (ACPI_EFI_ERROR (EfiStatus))
574 {
575 if (EfiStatus == ACPI_EFI_NOT_READY)
576 {
577 goto WaitKey;
578 }
579 errno = EIO;
580 Length = -EIO;
581 fprintf (stderr,
582 "SIMPLE_INPUT_INTERFACE->ReadKeyStroke() failure.\n");
583 goto ErrorExit;
584 }
585
586 switch (Key.UnicodeChar)
587 {
588 case ACPI_EFI_KEY_CTRL_C:
589
590 break;
591
592 case ACPI_EFI_KEY_ENTER:
593
594 *(ACPI_ADD_PTR (UINT8, Buffer, Pos)) = (UINT8) ACPI_EFI_ASCII_CR;
595 if (Pos < ReadSize - 1)
596 {
597 /* Drop CR in case we don't have sufficient buffer */
598
599 Pos++;
600 }
601 *(ACPI_ADD_PTR (UINT8, Buffer, Pos)) = (UINT8) ACPI_EFI_ASCII_NL;
602 Pos++;
603 break;
604
605 case ACPI_EFI_KEY_BACKSPACE:
606
607 *(ACPI_ADD_PTR (UINT8, Buffer, Pos)) = (UINT8) ACPI_EFI_ASCII_DEL;
608 Pos++;
609 break;
610
611 case ACPI_EFI_KEY_ESC:
612
613 *(ACPI_ADD_PTR (UINT8, Buffer, Pos)) = (UINT8) ACPI_EFI_ASCII_ESC;
614 Pos++;
615 break;
616
617 default:
618
619 *(ACPI_ADD_PTR (UINT8, Buffer, Pos)) = (UINT8) Key.UnicodeChar;
620 Pos++;
621 break;
622 }
623 }
624 Length = (int) Pos;
625 }
626 else
627 {
628 EfiFile = (ACPI_EFI_FILE_HANDLE) File;
629 if (!EfiFile)
630 {
631 errno = EINVAL;
632 goto ErrorExit;
633 }
634
635 EfiStatus = uefi_call_wrapper (AcpiGbl_EfiCurrentVolume->Read, 3,
636 EfiFile, &ReadSize, Buffer);
637 if (ACPI_EFI_ERROR (EfiStatus))
638 {
639 fprintf (stderr, "EFI_FILE_HANDLE->Read() failure.\n");
640 errno = EIO;
641 Length = -EIO;
642 goto ErrorExit;
643 }
644 Length = (int) ReadSize;
645 }
646
647 ErrorExit:
648
649 return (Length);
650 }
651
652
653 /*******************************************************************************
654 *
655 * FUNCTION: AcpiEfiFlushFile
656 *
657 * PARAMETERS: File - File descriptor
658 * Begin - String with boundary
659 * End - Boundary of the string
660 * Pos - Current position
661 * FlushAll - Whether checking boundary before flushing
662 *
663 * RETURN: Updated position
664 *
665 * DESCRIPTION: Flush cached buffer to the file.
666 *
667 ******************************************************************************/
668
669 static CHAR16 *
AcpiEfiFlushFile(FILE * File,CHAR16 * Begin,CHAR16 * End,CHAR16 * Pos,BOOLEAN FlushAll)670 AcpiEfiFlushFile (
671 FILE *File,
672 CHAR16 *Begin,
673 CHAR16 *End,
674 CHAR16 *Pos,
675 BOOLEAN FlushAll)
676 {
677 ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE *Out;
678
679
680 if (File == stdout || File == stderr)
681 {
682 Out = ACPI_CAST_PTR (ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE, File);
683
684 if (FlushAll || Pos >= (End - 1))
685 {
686 *Pos = 0;
687 uefi_call_wrapper (Out->OutputString, 2, Out, Begin);
688 Pos = Begin;
689 }
690 }
691
692 return (Pos);
693 }
694
695
696 /*******************************************************************************
697 *
698 * FUNCTION: fwrite
699 *
700 * PARAMETERS: Buffer - Data buffer
701 * Size - Data block size
702 * Count - Number of data blocks
703 * File - File descriptor
704 *
705 * RETURN: Size of successfully written buffer
706 *
707 * DESCRIPTION: Write to a file.
708 *
709 ******************************************************************************/
710
711 int
fwrite(void * Buffer,ACPI_SIZE Size,ACPI_SIZE Count,FILE * File)712 fwrite (
713 void *Buffer,
714 ACPI_SIZE Size,
715 ACPI_SIZE Count,
716 FILE *File)
717 {
718 int Length = -EINVAL;
719 CHAR16 String[ACPI_EFI_PRINT_LENGTH];
720 const char *Ascii;
721 CHAR16 *End;
722 CHAR16 *Pos;
723 ACPI_SIZE i, j;
724 ACPI_EFI_FILE_HANDLE EfiFile;
725 UINTN WriteSize;
726 ACPI_EFI_STATUS EfiStatus;
727
728
729 if (File == stdin)
730 {
731 /* Do not support write operations on input console */
732 }
733 else if (File == stdout || File == stderr)
734 {
735 Pos = String;
736 End = String + ACPI_EFI_PRINT_LENGTH - 1;
737 Ascii = ACPI_CAST_PTR (const char, Buffer);
738 Length = 0;
739
740 for (j = 0; j < Count; j++)
741 {
742 for (i = 0; i < Size; i++)
743 {
744 if (*Ascii == '\n')
745 {
746 *Pos++ = '\r';
747 Pos = AcpiEfiFlushFile (File, String,
748 End, Pos, FALSE);
749 }
750 *Pos++ = *Ascii++;
751 Length++;
752 Pos = AcpiEfiFlushFile (File, String,
753 End, Pos, FALSE);
754 }
755 }
756 Pos = AcpiEfiFlushFile (File, String, End, Pos, TRUE);
757 }
758 else
759 {
760 EfiFile = (ACPI_EFI_FILE_HANDLE) File;
761 if (!EfiFile)
762 {
763 errno = EINVAL;
764 goto ErrorExit;
765 }
766 WriteSize = Size * Count;
767
768 EfiStatus = uefi_call_wrapper (AcpiGbl_EfiCurrentVolume->Write, 3,
769 EfiFile, &WriteSize, Buffer);
770 if (ACPI_EFI_ERROR (EfiStatus))
771 {
772 fprintf (stderr, "EFI_FILE_HANDLE->Write() failure.\n");
773 errno = EIO;
774 goto ErrorExit;
775 }
776 Length = (int) WriteSize;
777 }
778
779 ErrorExit:
780
781 return (Length);
782 }
783
784
785 /*******************************************************************************
786 *
787 * FUNCTION: AcpiEfiGetFileInfo
788 *
789 * PARAMETERS: File - File descriptor
790 * InfoPtr - Pointer to contain file information
791 *
792 * RETURN: Clibrary error code
793 *
794 * DESCRIPTION: Get file information.
795 *
796 ******************************************************************************/
797
798 static int
AcpiEfiGetFileInfo(FILE * File,ACPI_EFI_FILE_INFO ** InfoPtr)799 AcpiEfiGetFileInfo (
800 FILE *File,
801 ACPI_EFI_FILE_INFO **InfoPtr)
802 {
803 ACPI_EFI_STATUS EfiStatus = ACPI_EFI_BUFFER_TOO_SMALL;
804 ACPI_EFI_FILE_INFO *Buffer = NULL;
805 UINTN BufferSize = SIZE_OF_ACPI_EFI_FILE_INFO + 200;
806 ACPI_EFI_FILE_HANDLE EfiFile;
807
808
809 if (!InfoPtr)
810 {
811 errno = EINVAL;
812 return (-EINVAL);
813 }
814
815 while (EfiStatus == ACPI_EFI_BUFFER_TOO_SMALL)
816 {
817 EfiFile = (ACPI_EFI_FILE_HANDLE) File;
818 Buffer = AcpiOsAllocate (BufferSize);
819 if (!Buffer)
820 {
821 errno = ENOMEM;
822 return (-ENOMEM);
823 }
824 EfiStatus = uefi_call_wrapper (EfiFile->GetInfo, 4, EfiFile,
825 &AcpiGbl_GenericFileInfo, &BufferSize, Buffer);
826 if (ACPI_EFI_ERROR (EfiStatus))
827 {
828 AcpiOsFree (Buffer);
829 if (EfiStatus != ACPI_EFI_BUFFER_TOO_SMALL)
830 {
831 errno = EIO;
832 return (-EIO);
833 }
834 }
835 }
836
837 *InfoPtr = Buffer;
838 return (0);
839 }
840
841
842 /*******************************************************************************
843 *
844 * FUNCTION: ftell
845 *
846 * PARAMETERS: File - File descriptor
847 *
848 * RETURN: current position
849 *
850 * DESCRIPTION: Get current file offset.
851 *
852 ******************************************************************************/
853
854 long
ftell(FILE * File)855 ftell (
856 FILE *File)
857 {
858 long Offset = -1;
859 UINT64 Current;
860 ACPI_EFI_STATUS EfiStatus;
861 ACPI_EFI_FILE_HANDLE EfiFile;
862
863
864 if (File == stdin || File == stdout || File == stderr)
865 {
866 Offset = 0;
867 }
868 else
869 {
870 EfiFile = (ACPI_EFI_FILE_HANDLE) File;
871
872 EfiStatus = uefi_call_wrapper (EfiFile->GetPosition, 2,
873 EfiFile, &Current);
874 if (ACPI_EFI_ERROR (EfiStatus))
875 {
876 goto ErrorExit;
877 }
878 else
879 {
880 Offset = (long) Current;
881 }
882 }
883
884 ErrorExit:
885 return (Offset);
886 }
887
888
889 /*******************************************************************************
890 *
891 * FUNCTION: fseek
892 *
893 * PARAMETERS: File - File descriptor
894 * Offset - File offset
895 * From - From begin/end of file
896 *
897 * RETURN: Status
898 *
899 * DESCRIPTION: Set current file offset.
900 *
901 ******************************************************************************/
902
903 int
fseek(FILE * File,long Offset,int From)904 fseek (
905 FILE *File,
906 long Offset,
907 int From)
908 {
909 ACPI_EFI_FILE_INFO *Info;
910 int Error;
911 ACPI_SIZE Size;
912 UINT64 Current;
913 ACPI_EFI_STATUS EfiStatus;
914 ACPI_EFI_FILE_HANDLE EfiFile;
915
916
917 if (File == stdin || File == stdout || File == stderr)
918 {
919 return (0);
920 }
921 else
922 {
923 EfiFile = (ACPI_EFI_FILE_HANDLE) File;
924 Error = AcpiEfiGetFileInfo (File, &Info);
925 if (Error)
926 {
927 return (Error);
928 }
929 Size = (ACPI_SIZE) (Info->FileSize);
930 AcpiOsFree (Info);
931
932 if (From == SEEK_CUR)
933 {
934 EfiStatus = uefi_call_wrapper (EfiFile->GetPosition, 2,
935 EfiFile, &Current);
936 if (ACPI_EFI_ERROR (EfiStatus))
937 {
938 errno = ERANGE;
939 return (-ERANGE);
940 }
941 Current += Offset;
942 }
943 else if (From == SEEK_END)
944 {
945 Current = Size - Offset;
946 }
947 else
948 {
949 Current = Offset;
950 }
951
952 EfiStatus = uefi_call_wrapper (EfiFile->SetPosition, 2,
953 EfiFile, Current);
954 if (ACPI_EFI_ERROR (EfiStatus))
955 {
956 errno = ERANGE;
957 return (-ERANGE);
958 }
959 }
960
961 return (0);
962 }
963
964
965 /******************************************************************************
966 *
967 * FUNCTION: AcpiEfiArgify
968 *
969 * PARAMETERS: String - Pointer to command line argument strings
970 * which are separated with spaces
971 * ArgcPtr - Return number of the arguments
972 * ArgvPtr - Return vector of the arguments
973 *
974 * RETURN: Clibraray error code
975 * -EINVAL: invalid parameter
976 * EAGAIN: try again
977 *
978 * DESCRIPTION: Convert EFI arguments into C arguments.
979 *
980 *****************************************************************************/
981
982 static int
AcpiEfiArgify(char * String,int * ArgcPtr,char *** ArgvPtr)983 AcpiEfiArgify (
984 char *String,
985 int *ArgcPtr,
986 char ***ArgvPtr)
987 {
988 char *CopyBuffer;
989 int MaxArgc = *ArgcPtr;
990 int Argc = 0;
991 char **Argv = *ArgvPtr;
992 char *Arg;
993 BOOLEAN IsSingleQuote = FALSE;
994 BOOLEAN IsDoubleQuote = FALSE;
995 BOOLEAN IsEscape = FALSE;
996
997
998 if (String == NULL)
999 {
1000 errno = EINVAL;
1001 return (-EINVAL);
1002 }
1003
1004 CopyBuffer = String;
1005
1006 while (*String != '\0')
1007 {
1008 while (isspace (*String))
1009 {
1010 *String++ = '\0';
1011 }
1012 Arg = CopyBuffer;
1013 while (*String != '\0')
1014 {
1015 if (isspace (*String) &&
1016 !IsSingleQuote && !IsDoubleQuote && !IsEscape)
1017 {
1018 *Arg++ = '\0';
1019 String++;
1020 break;
1021 }
1022 if (IsEscape)
1023 {
1024 IsEscape = FALSE;
1025 *Arg++ = *String;
1026 }
1027 else if (*String == '\\')
1028 {
1029 IsEscape = TRUE;
1030 }
1031 else if (IsSingleQuote)
1032 {
1033 if (*String == '\'')
1034 {
1035 IsSingleQuote = FALSE;
1036 *Arg++ = '\0';
1037 }
1038 else
1039 {
1040 *Arg++ = *String;
1041 }
1042 }
1043 else if (IsDoubleQuote)
1044 {
1045 if (*String == '"')
1046 {
1047 IsDoubleQuote = FALSE;
1048 *Arg = '\0';
1049 }
1050 else
1051 {
1052 *Arg++ = *String;
1053 }
1054 }
1055 else
1056 {
1057 if (*String == '\'')
1058 {
1059 IsSingleQuote = TRUE;
1060 }
1061 else if (*String == '"')
1062 {
1063 IsDoubleQuote = TRUE;
1064 }
1065 else
1066 {
1067 *Arg++ = *String;
1068 }
1069 }
1070 String++;
1071 }
1072 if (Argv && Argc < MaxArgc)
1073 {
1074 Argv[Argc] = CopyBuffer;
1075 }
1076 Argc++;
1077 CopyBuffer = Arg;
1078 }
1079 if (Argv && Argc < MaxArgc)
1080 {
1081 Argv[Argc] = NULL;
1082 }
1083
1084 *ArgcPtr = Argc;
1085 *ArgvPtr = Argv;
1086
1087 if (MaxArgc < Argc)
1088 {
1089 errno = EAGAIN;
1090 return (-ENOMEM);
1091 }
1092 return (0);
1093 }
1094
1095
1096 /******************************************************************************
1097 *
1098 * FUNCTION: AcpiEfiConvertArgcv
1099 *
1100 * PARAMETERS: LoadOptions - Pointer to the EFI options buffer, which
1101 * is NULL terminated
1102 * LoadOptionsSize - Size of the EFI options buffer
1103 * ArgcPtr - Return number of the arguments
1104 * ArgvPtr - Return vector of the arguments
1105 * BufferPtr - Buffer to contain the argument strings
1106 *
1107 * RETURN: Clibrary error code
1108 *
1109 * DESCRIPTION: Convert EFI arguments into C arguments.
1110 *
1111 *****************************************************************************/
1112
1113 static int
AcpiEfiConvertArgcv(CHAR16 * LoadOptions,UINT32 LoadOptionsSize,int * ArgcPtr,char *** ArgvPtr,char ** BufferPtr)1114 AcpiEfiConvertArgcv (
1115 CHAR16 *LoadOptions,
1116 UINT32 LoadOptionsSize,
1117 int *ArgcPtr,
1118 char ***ArgvPtr,
1119 char **BufferPtr)
1120 {
1121 int Error = 0;
1122 UINT32 Count = LoadOptionsSize / sizeof (CHAR16);
1123 UINT32 i;
1124 CHAR16 *From;
1125 char *To;
1126 int Argc = 0;
1127 char **Argv = NULL;
1128 char *Buffer;
1129
1130
1131 /* Prepare a buffer to contain the argument strings */
1132
1133 Buffer = ACPI_ALLOCATE_ZEROED (Count);
1134 if (!Buffer)
1135 {
1136 errno = ENOMEM;
1137 Error = -ENOMEM;
1138 goto ErrorExit;
1139 }
1140
1141 TryAgain:
1142
1143 /* Extend the argument vector */
1144
1145 if (Argv)
1146 {
1147 ACPI_FREE (Argv);
1148 Argv = NULL;
1149 }
1150 if (Argc > 0)
1151 {
1152 Argv = ACPI_ALLOCATE_ZEROED (sizeof (char *) * (Argc + 1));
1153 if (!Argv)
1154 {
1155 errno = ENOMEM;
1156 Error = -ENOMEM;
1157 goto ErrorExit;
1158 }
1159 }
1160
1161 /*
1162 * Note: As AcpiEfiArgify() will modify the content of the buffer, so
1163 * we need to restore it each time before invoking
1164 * AcpiEfiArgify().
1165 */
1166 From = LoadOptions;
1167 To = ACPI_CAST_PTR (char, Buffer);
1168 for (i = 0; i < Count; i++)
1169 {
1170 *To++ = (char) *From++;
1171 }
1172
1173 /*
1174 * The "Buffer" will contain NULL terminated strings after invoking
1175 * AcpiEfiArgify(). The number of the strings are saved in Argc and the
1176 * pointers of the strings are saved in Argv.
1177 */
1178 Error = AcpiEfiArgify (Buffer, &Argc, &Argv);
1179 if (Error && errno == EAGAIN)
1180 {
1181 goto TryAgain;
1182 }
1183
1184 ErrorExit:
1185
1186 if (Error)
1187 {
1188 ACPI_FREE (Buffer);
1189 ACPI_FREE (Argv);
1190 }
1191 else
1192 {
1193 *ArgcPtr = Argc;
1194 *ArgvPtr = Argv;
1195 *BufferPtr = Buffer;
1196 }
1197 return (Error);
1198 }
1199
1200
1201 /******************************************************************************
1202 *
1203 * FUNCTION: efi_main
1204 *
1205 * PARAMETERS: Image - EFI image handle
1206 * SystemTab - EFI system table
1207 *
1208 * RETURN: EFI Status
1209 *
1210 * DESCRIPTION: Entry point of EFI executable
1211 *
1212 *****************************************************************************/
1213
1214 ACPI_EFI_STATUS
efi_main(ACPI_EFI_HANDLE Image,ACPI_EFI_SYSTEM_TABLE * SystemTab)1215 efi_main (
1216 ACPI_EFI_HANDLE Image,
1217 ACPI_EFI_SYSTEM_TABLE *SystemTab)
1218 {
1219 ACPI_EFI_LOADED_IMAGE *Info;
1220 ACPI_EFI_STATUS EfiStatus = ACPI_EFI_SUCCESS;
1221 int Error;
1222 int argc;
1223 char **argv = NULL;
1224 char *OptBuffer = NULL;
1225 ACPI_EFI_FILE_IO_INTERFACE *Volume = NULL;
1226
1227
1228 /* Initialize global variables */
1229
1230 ST = SystemTab;
1231 BS = SystemTab->BootServices;
1232 RT = SystemTab->RuntimeServices;
1233 stdin = ACPI_CAST_PTR (ACPI_EFI_FILE, SystemTab->ConIn);
1234 stdout = ACPI_CAST_PTR (ACPI_EFI_FILE, SystemTab->ConOut);
1235 stderr = ACPI_CAST_PTR (ACPI_EFI_FILE, SystemTab->ConOut);
1236
1237 /* Disable the platform watchdog timer if we go interactive */
1238
1239 uefi_call_wrapper(BS->SetWatchdogTimer, 4, 0, 0x0, 0, NULL);
1240
1241 /* Retrieve image information */
1242
1243 EfiStatus = uefi_call_wrapper (BS->HandleProtocol, 3,
1244 Image, &AcpiGbl_LoadedImageProtocol, ACPI_CAST_PTR (VOID, &Info));
1245 if (ACPI_EFI_ERROR (EfiStatus))
1246 {
1247 fprintf (stderr,
1248 "EFI_BOOT_SERVICES->HandleProtocol(LoadedImageProtocol) failure.\n");
1249 return (EfiStatus);
1250 }
1251
1252 EfiStatus = uefi_call_wrapper (BS->HandleProtocol, 3,
1253 Info->DeviceHandle, &AcpiGbl_FileSystemProtocol, (void **) &Volume);
1254 if (ACPI_EFI_ERROR (EfiStatus))
1255 {
1256 fprintf (stderr,
1257 "EFI_BOOT_SERVICES->HandleProtocol(FileSystemProtocol) failure.\n");
1258 return (EfiStatus);
1259 }
1260 EfiStatus = uefi_call_wrapper (Volume->OpenVolume, 2,
1261 Volume, &AcpiGbl_EfiCurrentVolume);
1262 if (ACPI_EFI_ERROR (EfiStatus))
1263 {
1264 fprintf (stderr, "EFI_FILE_IO_INTERFACE->OpenVolume() failure.\n");
1265 return (EfiStatus);
1266 }
1267
1268 Error = AcpiEfiConvertArgcv (Info->LoadOptions,
1269 Info->LoadOptionsSize, &argc, &argv, &OptBuffer);
1270 if (Error)
1271 {
1272 EfiStatus = ACPI_EFI_DEVICE_ERROR;
1273 goto ErrorAlloc;
1274 }
1275
1276 acpi_main (argc, argv);
1277
1278 ErrorAlloc:
1279
1280 if (argv)
1281 {
1282 ACPI_FREE (argv);
1283 }
1284 if (OptBuffer)
1285 {
1286 ACPI_FREE (OptBuffer);
1287 }
1288
1289 return (EfiStatus);
1290 }
1291
1292 #ifdef _EDK2_EFI
1293 EFI_STATUS
1294 EFIAPI
UefiMain(EFI_HANDLE Image,EFI_SYSTEM_TABLE * SystemTab)1295 UefiMain (
1296 EFI_HANDLE Image,
1297 EFI_SYSTEM_TABLE *SystemTab)
1298 {
1299 EFI_STATUS EfiStatus;
1300
1301
1302 EfiStatus = (EFI_STATUS) efi_main (
1303 (ACPI_EFI_HANDLE) Image, (ACPI_EFI_SYSTEM_TABLE *) SystemTab);
1304 return (EfiStatus);
1305 }
1306 #endif
1307