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