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