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