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