1 /******************************************************************************
2  *
3  * Module Name: osefixf - EFI OSL interfaces
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "acpi.h"
45 #include "accommon.h"
46 #include "acapps.h"
47 
48 #define _COMPONENT          ACPI_OS_SERVICES
49         ACPI_MODULE_NAME    ("osefixf")
50 
51 
52 /* Local definitions */
53 
54 #define ACPI_EFI_PRINT_LENGTH   256
55 
56 
57 /* Local prototypes */
58 
59 static ACPI_STATUS
60 AcpiEfiArgify (
61     char                    *String,
62     int                     *ArgcPtr,
63     char                    ***ArgvPtr);
64 
65 static BOOLEAN
66 AcpiEfiCompareGuid (
67     EFI_GUID                *Guid1,
68     EFI_GUID                *Guid2);
69 
70 static ACPI_STATUS
71 AcpiEfiConvertArgcv (
72     CHAR16                  *LoadOpt,
73     UINT32                  LoadOptSize,
74     int                     *ArgcPtr,
75     char                    ***ArgvPtr,
76     char                    **BufferPtr);
77 
78 static ACPI_PHYSICAL_ADDRESS
79 AcpiEfiGetRsdpViaGuid (
80     EFI_GUID                *Guid);
81 
82 static CHAR16 *
83 AcpiEfiFlushFile (
84     ACPI_FILE               File,
85     CHAR16                  *Begin,
86     CHAR16                  *End,
87     CHAR16                  *Pos,
88     BOOLEAN                 FlushAll);
89 
90 
91 /* Local variables */
92 
93 static EFI_FILE_HANDLE      AcpiGbl_EfiCurrentVolume = NULL;
94 EFI_GUID                    AcpiGbl_LoadedImageProtocol = LOADED_IMAGE_PROTOCOL;
95 EFI_GUID                    AcpiGbl_TextInProtocol = SIMPLE_TEXT_INPUT_PROTOCOL;
96 EFI_GUID                    AcpiGbl_TextOutProtocol = SIMPLE_TEXT_OUTPUT_PROTOCOL;
97 EFI_GUID                    AcpiGbl_FileSystemProtocol = SIMPLE_FILE_SYSTEM_PROTOCOL;
98 
99 
100 /******************************************************************************
101  *
102  * FUNCTION:    AcpiEfiGetRsdpViaGuid
103  *
104  * PARAMETERS:  Guid1               - GUID to compare
105  *              Guid2               - GUID to compare
106  *
107  * RETURN:      TRUE if Guid1 == Guid2
108  *
109  * DESCRIPTION: Compares two GUIDs
110  *
111  *****************************************************************************/
112 
113 static BOOLEAN
AcpiEfiCompareGuid(EFI_GUID * Guid1,EFI_GUID * Guid2)114 AcpiEfiCompareGuid (
115     EFI_GUID                *Guid1,
116     EFI_GUID                *Guid2)
117 {
118     INT32                   *g1;
119     INT32                   *g2;
120     INT32                   r;
121 
122 
123     g1 = (INT32 *) Guid1;
124     g2 = (INT32 *) Guid2;
125 
126     r  = g1[0] - g2[0];
127     r |= g1[1] - g2[1];
128     r |= g1[2] - g2[2];
129     r |= g1[3] - g2[3];
130 
131     return (r ? FALSE : TRUE);
132 }
133 
134 
135 /******************************************************************************
136  *
137  * FUNCTION:    AcpiEfiGetRsdpViaGuid
138  *
139  * PARAMETERS:  None
140  *
141  * RETURN:      RSDP address if found
142  *
143  * DESCRIPTION: Find RSDP address via EFI using specified GUID.
144  *
145  *****************************************************************************/
146 
147 static ACPI_PHYSICAL_ADDRESS
AcpiEfiGetRsdpViaGuid(EFI_GUID * Guid)148 AcpiEfiGetRsdpViaGuid (
149     EFI_GUID                *Guid)
150 {
151     ACPI_PHYSICAL_ADDRESS   Address = 0;
152     int                     i;
153 
154 
155     for (i = 0; i < ST->NumberOfTableEntries; i++)
156     {
157         if (AcpiEfiCompareGuid (&ST->ConfigurationTable[i].VendorGuid, Guid))
158         {
159             Address = ACPI_PTR_TO_PHYSADDR (
160                     ST->ConfigurationTable[i].VendorTable);
161             break;
162         }
163     }
164 
165     return (Address);
166 }
167 
168 
169 /******************************************************************************
170  *
171  * FUNCTION:    AcpiOsGetRootPointer
172  *
173  * PARAMETERS:  None
174  *
175  * RETURN:      RSDP physical address
176  *
177  * DESCRIPTION: Gets the ACPI root pointer (RSDP)
178  *
179  *****************************************************************************/
180 
181 ACPI_PHYSICAL_ADDRESS
AcpiOsGetRootPointer(void)182 AcpiOsGetRootPointer (
183     void)
184 {
185     ACPI_PHYSICAL_ADDRESS   Address;
186     EFI_GUID                Guid10 = ACPI_TABLE_GUID;
187     EFI_GUID                Guid20 = ACPI_20_TABLE_GUID;
188 
189 
190     Address = AcpiEfiGetRsdpViaGuid (&Guid20);
191     if (!Address)
192     {
193         Address = AcpiEfiGetRsdpViaGuid (&Guid10);
194     }
195 
196     return (Address);
197 }
198 
199 
200 /******************************************************************************
201  *
202  * FUNCTION:    AcpiOsMapMemory
203  *
204  * PARAMETERS:  where               - Physical address of memory to be mapped
205  *              length              - How much memory to map
206  *
207  * RETURN:      Pointer to mapped memory. Null on error.
208  *
209  * DESCRIPTION: Map physical memory into caller's address space
210  *
211  *****************************************************************************/
212 
213 void *
AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS where,ACPI_SIZE length)214 AcpiOsMapMemory (
215     ACPI_PHYSICAL_ADDRESS   where,
216     ACPI_SIZE               length)
217 {
218 
219     return (ACPI_TO_POINTER ((ACPI_SIZE) where));
220 }
221 
222 
223 /******************************************************************************
224  *
225  * FUNCTION:    AcpiOsUnmapMemory
226  *
227  * PARAMETERS:  where               - Logical address of memory to be unmapped
228  *              length              - How much memory to unmap
229  *
230  * RETURN:      None
231  *
232  * DESCRIPTION: Delete a previously created mapping. Where and Length must
233  *              correspond to a previous mapping exactly.
234  *
235  *****************************************************************************/
236 
237 void
AcpiOsUnmapMemory(void * where,ACPI_SIZE length)238 AcpiOsUnmapMemory (
239     void                    *where,
240     ACPI_SIZE               length)
241 {
242 
243     return;
244 }
245 
246 
247 /******************************************************************************
248  *
249  * FUNCTION:    Spinlock interfaces
250  *
251  * DESCRIPTION: No-op on single threaded BIOS
252  *
253  *****************************************************************************/
254 
255 ACPI_STATUS
AcpiOsCreateLock(ACPI_SPINLOCK * OutHandle)256 AcpiOsCreateLock (
257     ACPI_SPINLOCK           *OutHandle)
258 {
259     return (AE_OK);
260 }
261 
262 void
AcpiOsDeleteLock(ACPI_SPINLOCK Handle)263 AcpiOsDeleteLock (
264     ACPI_SPINLOCK           Handle)
265 {
266 }
267 
268 ACPI_CPU_FLAGS
AcpiOsAcquireLock(ACPI_SPINLOCK Handle)269 AcpiOsAcquireLock (
270     ACPI_SPINLOCK           Handle)
271 {
272     return (0);
273 }
274 
275 void
AcpiOsReleaseLock(ACPI_SPINLOCK Handle,ACPI_CPU_FLAGS Flags)276 AcpiOsReleaseLock (
277     ACPI_SPINLOCK           Handle,
278     ACPI_CPU_FLAGS          Flags)
279 {
280 }
281 
282 
283 /******************************************************************************
284  *
285  * FUNCTION:    AcpiOsAllocate
286  *
287  * PARAMETERS:  Size                - Amount to allocate, in bytes
288  *
289  * RETURN:      Pointer to the new allocation. Null on error.
290  *
291  * DESCRIPTION: Allocate memory. Algorithm is dependent on the OS.
292  *
293  *****************************************************************************/
294 
295 void *
AcpiOsAllocate(ACPI_SIZE Size)296 AcpiOsAllocate (
297     ACPI_SIZE               Size)
298 {
299     EFI_STATUS              EfiStatus;
300     void                    *Mem;
301 
302 
303     EfiStatus = uefi_call_wrapper (BS->AllocatePool, 3,
304         EfiLoaderData, Size, &Mem);
305     if (EFI_ERROR (EfiStatus))
306     {
307         AcpiLogError ("EFI_BOOT_SERVICES->AllocatePool(EfiLoaderData) failure.\n");
308         return (NULL);
309     }
310 
311     return (Mem);
312 }
313 
314 
315 #ifdef USE_NATIVE_ALLOCATE_ZEROED
316 /******************************************************************************
317  *
318  * FUNCTION:    AcpiOsAllocateZeroed
319  *
320  * PARAMETERS:  Size                - Amount to allocate, in bytes
321  *
322  * RETURN:      Pointer to the new allocation. Null on error.
323  *
324  * DESCRIPTION: Allocate and zero memory. Algorithm is dependent on the OS.
325  *
326  *****************************************************************************/
327 
328 void *
AcpiOsAllocateZeroed(ACPI_SIZE Size)329 AcpiOsAllocateZeroed (
330     ACPI_SIZE               Size)
331 {
332     void                    *Mem;
333 
334 
335     Mem = AcpiOsAllocate (Size);
336     if (Mem)
337     {
338         memset (Mem, 0, Size);
339     }
340 
341     return (Mem);
342 }
343 #endif
344 
345 
346 /******************************************************************************
347  *
348  * FUNCTION:    AcpiOsFree
349  *
350  * PARAMETERS:  Mem                 - Pointer to previously allocated memory
351  *
352  * RETURN:      None
353  *
354  * DESCRIPTION: Free memory allocated via AcpiOsAllocate
355  *
356  *****************************************************************************/
357 
358 void
AcpiOsFree(void * Mem)359 AcpiOsFree (
360     void                    *Mem)
361 {
362 
363     uefi_call_wrapper (BS->FreePool, 1, Mem);
364 }
365 
366 
367 /*******************************************************************************
368  *
369  * FUNCTION:    AcpiOsOpenFile
370  *
371  * PARAMETERS:  Path                - File path
372  *              Modes               - File operation type
373  *
374  * RETURN:      File descriptor
375  *
376  * DESCRIPTION: Open a file for reading (ACPI_FILE_READING) or/and writing
377  *              (ACPI_FILE_WRITING).
378  *
379  ******************************************************************************/
380 
381 ACPI_FILE
AcpiOsOpenFile(const char * Path,UINT8 Modes)382 AcpiOsOpenFile (
383     const char              *Path,
384     UINT8                   Modes)
385 {
386     EFI_STATUS              EfiStatus = EFI_SUCCESS;
387     UINT64                  OpenModes;
388     EFI_FILE_HANDLE         EfiFile = NULL;
389     CHAR16                  *Path16 = NULL;
390     CHAR16                  *Pos16;
391     const char              *Pos;
392     INTN                    Count, i;
393 
394 
395     if (!Path)
396     {
397         return (NULL);
398     }
399 
400     /* Convert modes */
401 
402     OpenModes = EFI_FILE_MODE_READ;
403     if (Modes & ACPI_FILE_WRITING)
404     {
405         OpenModes |= (EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE);
406     }
407 
408     /* Allocate path buffer */
409 
410     Count = strlen (Path);
411     Path16 = ACPI_ALLOCATE_ZEROED ((Count + 1) * sizeof (CHAR16));
412     if (!Path16)
413     {
414         EfiStatus = EFI_BAD_BUFFER_SIZE;
415         goto ErrorExit;
416     }
417     Pos = Path;
418     Pos16 = Path16;
419     while (*Pos == '/' || *Pos == '\\')
420     {
421         Pos++;
422         Count--;
423     }
424     for (i = 0; i < Count; i++)
425     {
426         if (*Pos == '/')
427         {
428             *Pos16++ = '\\';
429             Pos++;
430         }
431         else
432         {
433             *Pos16++ = *Pos++;
434         }
435     }
436     *Pos16 = '\0';
437 
438     EfiStatus = uefi_call_wrapper (AcpiGbl_EfiCurrentVolume->Open, 5,
439         AcpiGbl_EfiCurrentVolume, &EfiFile, Path16, OpenModes, 0);
440     if (EFI_ERROR (EfiStatus))
441     {
442         AcpiLogError ("EFI_FILE_HANDLE->Open() failure.\n");
443         goto ErrorExit;
444     }
445 
446 ErrorExit:
447 
448     if (Path16)
449     {
450         ACPI_FREE (Path16);
451     }
452 
453     return ((ACPI_FILE) EfiFile);
454 }
455 
456 
457 /*******************************************************************************
458  *
459  * FUNCTION:    AcpiOsCloseFile
460  *
461  * PARAMETERS:  File                - File descriptor
462  *
463  * RETURN:      None.
464  *
465  * DESCRIPTION: Close a file.
466  *
467  ******************************************************************************/
468 
469 void
AcpiOsCloseFile(ACPI_FILE File)470 AcpiOsCloseFile (
471     ACPI_FILE               File)
472 {
473     EFI_FILE_HANDLE         EfiFile;
474 
475 
476     if (File == ACPI_FILE_OUT ||
477         File == ACPI_FILE_ERR)
478     {
479         return;
480     }
481     EfiFile = (EFI_FILE_HANDLE) File;
482     (void) uefi_call_wrapper (AcpiGbl_EfiCurrentVolume->Close, 1, EfiFile);
483 
484     return;
485 }
486 
487 
488 /*******************************************************************************
489  *
490  * FUNCTION:    AcpiOsReadFile
491  *
492  * PARAMETERS:  File                - File descriptor
493  *              Buffer              - Data buffer
494  *              Size                - Data block size
495  *              Count               - Number of data blocks
496  *
497  * RETURN:      Size of successfully read buffer
498  *
499  * DESCRIPTION: Read from a file.
500  *
501  ******************************************************************************/
502 
503 int
AcpiOsReadFile(ACPI_FILE File,void * Buffer,ACPI_SIZE Size,ACPI_SIZE Count)504 AcpiOsReadFile (
505     ACPI_FILE               File,
506     void                    *Buffer,
507     ACPI_SIZE               Size,
508     ACPI_SIZE               Count)
509 {
510     int                     Length = -1;
511     EFI_FILE_HANDLE         EfiFile;
512     UINTN                   ReadSize;
513     EFI_STATUS              EfiStatus;
514 
515 
516     if (File == ACPI_FILE_OUT ||
517         File == ACPI_FILE_ERR)
518     {
519     }
520     else
521     {
522         EfiFile = (EFI_FILE_HANDLE) File;
523         if (!EfiFile)
524         {
525             goto ErrorExit;
526         }
527         ReadSize = Size * Count;
528 
529         EfiStatus = uefi_call_wrapper (AcpiGbl_EfiCurrentVolume->Read, 3,
530             EfiFile, &ReadSize, Buffer);
531         if (EFI_ERROR (EfiStatus))
532         {
533             AcpiLogError ("EFI_FILE_HANDLE->Read() failure.\n");
534             goto ErrorExit;
535         }
536         Length = ReadSize;
537     }
538 
539 ErrorExit:
540 
541     return (Length);
542 }
543 
544 
545 /*******************************************************************************
546  *
547  * FUNCTION:    AcpiEfiFlushFile
548  *
549  * PARAMETERS:  File                - File descriptor
550  *              Begin               - String with boundary
551  *              End                 - Boundary of the string
552  *              Pos                 - Current position
553  *              FlushAll            - Whether checking boundary before flushing
554  *
555  * RETURN:      Updated position
556  *
557  * DESCRIPTION: Flush cached buffer to the file.
558  *
559  ******************************************************************************/
560 
561 static CHAR16 *
AcpiEfiFlushFile(ACPI_FILE File,CHAR16 * Begin,CHAR16 * End,CHAR16 * Pos,BOOLEAN FlushAll)562 AcpiEfiFlushFile (
563     ACPI_FILE               File,
564     CHAR16                  *Begin,
565     CHAR16                  *End,
566     CHAR16                  *Pos,
567     BOOLEAN                 FlushAll)
568 {
569 
570     if (FlushAll || Pos >= (End - 1))
571     {
572         *Pos = 0;
573         uefi_call_wrapper (File->OutputString, 2, File, Begin);
574         Pos = Begin;
575     }
576 
577     return (Pos);
578 }
579 
580 
581 /*******************************************************************************
582  *
583  * FUNCTION:    AcpiOsWriteFile
584  *
585  * PARAMETERS:  File                - File descriptor
586  *              Buffer              - Data buffer
587  *              Size                - Data block size
588  *              Count               - Number of data blocks
589  *
590  * RETURN:      Size of successfully written buffer
591  *
592  * DESCRIPTION: Write to a file.
593  *
594  ******************************************************************************/
595 
596 int
AcpiOsWriteFile(ACPI_FILE File,void * Buffer,ACPI_SIZE Size,ACPI_SIZE Count)597 AcpiOsWriteFile (
598     ACPI_FILE               File,
599     void                    *Buffer,
600     ACPI_SIZE               Size,
601     ACPI_SIZE               Count)
602 {
603     int                     Length = -1;
604     CHAR16                  String[ACPI_EFI_PRINT_LENGTH];
605     const char              *Ascii;
606     CHAR16                  *End;
607     CHAR16                  *Pos;
608     int                     i, j;
609     EFI_FILE_HANDLE         EfiFile;
610     UINTN                   WriteSize;
611     EFI_STATUS              EfiStatus;
612 
613 
614     if (File == ACPI_FILE_OUT ||
615         File == ACPI_FILE_ERR)
616     {
617         Pos = String;
618         End = String + ACPI_EFI_PRINT_LENGTH - 1;
619         Ascii = ACPI_CAST_PTR (const char, Buffer);
620         Length = 0;
621 
622         for (j = 0; j < Count; j++)
623         {
624             for (i = 0; i < Size; i++)
625             {
626                 if (*Ascii == '\n')
627                 {
628                     *Pos++ = '\r';
629                     Pos = AcpiEfiFlushFile (File, String,
630                             End, Pos, FALSE);
631                 }
632                 *Pos++ = *Ascii++;
633                 Length++;
634                 Pos = AcpiEfiFlushFile (File, String,
635                         End, Pos, FALSE);
636             }
637         }
638         Pos = AcpiEfiFlushFile (File, String, End, Pos, TRUE);
639     }
640     else
641     {
642         EfiFile = (EFI_FILE_HANDLE) File;
643         if (!EfiFile)
644         {
645             goto ErrorExit;
646         }
647         WriteSize = Size * Count;
648 
649         EfiStatus = uefi_call_wrapper (AcpiGbl_EfiCurrentVolume->Write, 3,
650             EfiFile, &WriteSize, Buffer);
651         if (EFI_ERROR (EfiStatus))
652         {
653             AcpiLogError ("EFI_FILE_HANDLE->Write() failure.\n");
654             goto ErrorExit;
655         }
656         Length = WriteSize;
657     }
658 
659 ErrorExit:
660 
661     return (Length);
662 }
663 
664 
665 /*******************************************************************************
666  *
667  * FUNCTION:    AcpiOsGetFileOffset
668  *
669  * PARAMETERS:  File                - File descriptor
670  *
671  * RETURN:      Size of current position
672  *
673  * DESCRIPTION: Get current file offset.
674  *
675  ******************************************************************************/
676 
677 long
AcpiOsGetFileOffset(ACPI_FILE File)678 AcpiOsGetFileOffset (
679     ACPI_FILE               File)
680 {
681     long                    Offset = -1;
682 
683 
684     return (Offset);
685 }
686 
687 
688 /*******************************************************************************
689  *
690  * FUNCTION:    AcpiOsSetFileOffset
691  *
692  * PARAMETERS:  File                - File descriptor
693  *              Offset              - File offset
694  *              From                - From begin/end of file
695  *
696  * RETURN:      Status
697  *
698  * DESCRIPTION: Set current file offset.
699  *
700  ******************************************************************************/
701 
702 ACPI_STATUS
AcpiOsSetFileOffset(ACPI_FILE File,long Offset,UINT8 From)703 AcpiOsSetFileOffset (
704     ACPI_FILE               File,
705     long                    Offset,
706     UINT8                   From)
707 {
708 
709     return (AE_SUPPORT);
710 }
711 
712 
713 /******************************************************************************
714  *
715  * FUNCTION:    AcpiOsPrintf
716  *
717  * PARAMETERS:  Format, ...         - Standard printf format
718  *
719  * RETURN:      None
720  *
721  * DESCRIPTION: Formatted output.
722  *
723  *****************************************************************************/
724 
725 void ACPI_INTERNAL_VAR_XFACE
AcpiOsPrintf(const char * Format,...)726 AcpiOsPrintf (
727     const char              *Format,
728     ...)
729 {
730     va_list                 Args;
731 
732 
733     va_start (Args, Format);
734     AcpiOsVprintf (Format, Args);
735     va_end (Args);
736 }
737 
738 
739 /******************************************************************************
740  *
741  * FUNCTION:    AcpiOsVprintf
742  *
743  * PARAMETERS:  Format              - Standard printf format
744  *              Args                - Argument list
745  *
746  * RETURN:      None
747  *
748  * DESCRIPTION: Formatted output with arguments list pointer.
749  *
750  *****************************************************************************/
751 
752 void
AcpiOsVprintf(const char * Format,va_list Args)753 AcpiOsVprintf (
754     const char              *Format,
755     va_list                 Args)
756 {
757 
758     (void) AcpiUtFileVprintf (ACPI_FILE_OUT, Format, Args);
759 }
760 
761 
762 /******************************************************************************
763  *
764  * FUNCTION:    AcpiOsInitialize
765  *
766  * PARAMETERS:  None
767  *
768  * RETURN:      Status
769  *
770  * DESCRIPTION: Initialize this module.
771  *
772  *****************************************************************************/
773 
774 ACPI_STATUS
AcpiOsInitialize(void)775 AcpiOsInitialize (
776     void)
777 {
778 
779     return (AE_OK);
780 }
781 
782 
783 /******************************************************************************
784  *
785  * FUNCTION:    AcpiEfiArgify
786  *
787  * PARAMETERS:  String              - Pointer to command line argument strings
788  *                                    which are seperated with spaces
789  *              ArgcPtr             - Return number of the arguments
790  *              ArgvPtr             - Return vector of the arguments
791  *
792  * RETURN:      Status
793  *
794  * DESCRIPTION: Convert EFI arguments into C arguments.
795  *
796  *****************************************************************************/
797 
798 static ACPI_STATUS
AcpiEfiArgify(char * String,int * ArgcPtr,char *** ArgvPtr)799 AcpiEfiArgify (
800     char                    *String,
801     int                     *ArgcPtr,
802     char                    ***ArgvPtr)
803 {
804     char                    *CopyBuffer;
805     int                     MaxArgc = *ArgcPtr;
806     int                     Argc = 0;
807     char                    **Argv = *ArgvPtr;
808     char                    *Arg;
809     BOOLEAN                 IsSingleQuote = FALSE;
810     BOOLEAN                 IsDoubleQuote = FALSE;
811     BOOLEAN                 IsEscape = FALSE;
812 
813 
814     if (String == NULL)
815     {
816         return (AE_BAD_PARAMETER);
817     }
818 
819     CopyBuffer = String;
820 
821     while (*String != '\0')
822     {
823         while (isspace (*String))
824         {
825             *String++ = '\0';
826         }
827         Arg = CopyBuffer;
828         while (*String != '\0')
829         {
830             if (isspace (*String) &&
831                 !IsSingleQuote && !IsDoubleQuote && !IsEscape)
832             {
833                 *Arg++ = '\0';
834                 String++;
835                 break;
836             }
837             if (IsEscape)
838             {
839                 IsEscape = FALSE;
840                 *Arg++ = *String;
841             }
842             else if (*String == '\\')
843             {
844                 IsEscape = TRUE;
845             }
846             else if (IsSingleQuote)
847             {
848                 if (*String == '\'')
849                 {
850                     IsSingleQuote = FALSE;
851                     *Arg++ = '\0';
852                 }
853                 else
854                 {
855                     *Arg++ = *String;
856                 }
857             }
858             else if (IsDoubleQuote)
859             {
860                 if (*String == '"')
861                 {
862                     IsDoubleQuote = FALSE;
863                     *Arg = '\0';
864                 }
865                 else
866                 {
867                     *Arg++ = *String;
868                 }
869             }
870             else
871             {
872                 if (*String == '\'')
873                 {
874                     IsSingleQuote = TRUE;
875                 }
876                 else if (*String == '"')
877                 {
878                     IsDoubleQuote = TRUE;
879                 }
880                 else
881                 {
882                     *Arg++ = *String;
883                 }
884             }
885             String++;
886         }
887         if (Argv && Argc < MaxArgc)
888         {
889             Argv[Argc] = CopyBuffer;
890         }
891         Argc++;
892         CopyBuffer = Arg;
893     }
894     if (Argv && Argc < MaxArgc)
895     {
896         Argv[Argc] = NULL;
897     }
898 
899     *ArgcPtr = Argc;
900     *ArgvPtr = Argv;
901 
902     return ((MaxArgc < Argc) ? AE_NO_MEMORY : AE_OK);
903 }
904 
905 
906 /******************************************************************************
907  *
908  * FUNCTION:    AcpiEfiConvertArgcv
909  *
910  * PARAMETERS:  LoadOptions         - Pointer to the EFI options buffer, which
911  *                                    is NULL terminated
912  *              LoadOptionsSize     - Size of the EFI options buffer
913  *              ArgcPtr             - Return number of the arguments
914  *              ArgvPtr             - Return vector of the arguments
915  *              BufferPtr           - Buffer to contain the argument strings
916  *
917  * RETURN:      Status
918  *
919  * DESCRIPTION: Convert EFI arguments into C arguments.
920  *
921  *****************************************************************************/
922 
923 static ACPI_STATUS
AcpiEfiConvertArgcv(CHAR16 * LoadOptions,UINT32 LoadOptionsSize,int * ArgcPtr,char *** ArgvPtr,char ** BufferPtr)924 AcpiEfiConvertArgcv (
925     CHAR16                  *LoadOptions,
926     UINT32                  LoadOptionsSize,
927     int                     *ArgcPtr,
928     char                    ***ArgvPtr,
929     char                    **BufferPtr)
930 {
931     ACPI_STATUS             Status = AE_OK;
932     UINT32                  Count = LoadOptionsSize / sizeof (CHAR16);
933     UINT32                  i;
934     CHAR16                  *From;
935     char                    *To;
936     int                     Argc = 0;
937     char                    **Argv = NULL;
938     char                    *Buffer;
939 
940 
941     /* Prepare a buffer to contain the argument strings */
942 
943     Buffer = ACPI_ALLOCATE_ZEROED (Count);
944     if (!Buffer)
945     {
946         Status = AE_NO_MEMORY;
947         goto ErrorExit;
948     }
949 
950 TryAgain:
951 
952     /* Extend the argument vector */
953 
954     if (Argv)
955     {
956         ACPI_FREE (Argv);
957         Argv = NULL;
958     }
959     if (Argc > 0)
960     {
961         Argv = ACPI_ALLOCATE_ZEROED (sizeof (char *) * (Argc + 1));
962         if (!Argv)
963         {
964             Status = AE_NO_MEMORY;
965             goto ErrorExit;
966         }
967     }
968 
969     /*
970      * Note: As AcpiEfiArgify() will modify the content of the buffer, so
971      *       we need to restore it each time before invoking
972      *       AcpiEfiArgify().
973      */
974     From = LoadOptions;
975     To = ACPI_CAST_PTR (char, Buffer);
976     for (i = 0; i < Count; i++)
977     {
978         *To++ = (char) *From++;
979     }
980 
981     /*
982      * The "Buffer" will contain NULL terminated strings after invoking
983      * AcpiEfiArgify(). The number of the strings are saved in Argc and the
984      * pointers of the strings are saved in Argv.
985      */
986     Status = AcpiEfiArgify (Buffer, &Argc, &Argv);
987     if (ACPI_FAILURE (Status))
988     {
989         if (Status == AE_NO_MEMORY)
990         {
991             goto TryAgain;
992         }
993     }
994 
995 ErrorExit:
996 
997     if (ACPI_FAILURE (Status))
998     {
999         ACPI_FREE (Buffer);
1000         ACPI_FREE (Argv);
1001     }
1002     else
1003     {
1004         *ArgcPtr = Argc;
1005         *ArgvPtr = Argv;
1006         *BufferPtr = Buffer;
1007     }
1008     return (Status);
1009 }
1010 
1011 
1012 /******************************************************************************
1013  *
1014  * FUNCTION:    efi_main
1015  *
1016  * PARAMETERS:  Image               - EFI image handle
1017  *              SystemTab           - EFI system table
1018  *
1019  * RETURN:      EFI Status
1020  *
1021  * DESCRIPTION: Entry point of EFI executable
1022  *
1023  *****************************************************************************/
1024 
1025 EFI_STATUS
efi_main(EFI_HANDLE Image,EFI_SYSTEM_TABLE * SystemTab)1026 efi_main (
1027     EFI_HANDLE              Image,
1028     EFI_SYSTEM_TABLE        *SystemTab)
1029 {
1030     EFI_LOADED_IMAGE        *Info;
1031     EFI_STATUS              EfiStatus = EFI_SUCCESS;
1032     ACPI_STATUS             Status;
1033     int                     argc;
1034     char                    **argv = NULL;
1035     char                    *OptBuffer = NULL;
1036     EFI_FILE_IO_INTERFACE   *Volume = NULL;
1037 
1038 
1039     /* Initialize global variables */
1040 
1041     ST = SystemTab;
1042     BS = SystemTab->BootServices;
1043 
1044     /* Retrieve image information */
1045 
1046     EfiStatus = uefi_call_wrapper (BS->HandleProtocol, 3,
1047         Image, &AcpiGbl_LoadedImageProtocol, ACPI_CAST_PTR (VOID, &Info));
1048     if (EFI_ERROR (EfiStatus))
1049     {
1050         AcpiLogError ("EFI_BOOT_SERVICES->HandleProtocol(LoadedImageProtocol) failure.\n");
1051         return (EfiStatus);
1052     }
1053 
1054     EfiStatus = uefi_call_wrapper (BS->HandleProtocol, 3,
1055         Info->DeviceHandle, &AcpiGbl_FileSystemProtocol, (void **) &Volume);
1056     if (EFI_ERROR (EfiStatus))
1057     {
1058         AcpiLogError ("EFI_BOOT_SERVICES->HandleProtocol(FileSystemProtocol) failure.\n");
1059         return (EfiStatus);
1060     }
1061     EfiStatus = uefi_call_wrapper (Volume->OpenVolume, 2,
1062         Volume, &AcpiGbl_EfiCurrentVolume);
1063     if (EFI_ERROR (EfiStatus))
1064     {
1065         AcpiLogError ("EFI_FILE_IO_INTERFACE->OpenVolume() failure.\n");
1066         return (EfiStatus);
1067     }
1068 
1069     Status = AcpiEfiConvertArgcv (Info->LoadOptions,
1070         Info->LoadOptionsSize, &argc, &argv, &OptBuffer);
1071     if (ACPI_FAILURE (Status))
1072     {
1073         EfiStatus = EFI_DEVICE_ERROR;
1074         goto ErrorAlloc;
1075     }
1076 
1077     acpi_main (argc, argv);
1078 
1079 ErrorAlloc:
1080 
1081     if (argv)
1082     {
1083         ACPI_FREE (argv);
1084     }
1085     if (OptBuffer)
1086     {
1087         ACPI_FREE (OptBuffer);
1088     }
1089 
1090     return (EfiStatus);
1091 }
1092