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