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