1 /****************************************************************************** 2 * 3 * Module Name: oseficlib - EFI specific CLibrary interfaces 4 * 5 *****************************************************************************/ 6 7 /****************************************************************************** 8 * 9 * 1. Copyright Notice 10 * 11 * Some or all of this work - Copyright (c) 1999 - 2023, Intel Corp. 12 * All rights reserved. 13 * 14 * 2. License 15 * 16 * 2.1. This is your license from Intel Corp. under its intellectual property 17 * rights. You may have additional license terms from the party that provided 18 * you this software, covering your right to use that party's intellectual 19 * property rights. 20 * 21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22 * copy of the source code appearing in this file ("Covered Code") an 23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24 * base code distributed originally by Intel ("Original Intel Code") to copy, 25 * make derivatives, distribute, use and display any portion of the Covered 26 * Code in any form, with the right to sublicense such rights; and 27 * 28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29 * license (with the right to sublicense), under only those claims of Intel 30 * patents that are infringed by the Original Intel Code, to make, use, sell, 31 * offer to sell, and import the Covered Code and derivative works thereof 32 * solely to the minimum extent necessary to exercise the above copyright 33 * license, and in no event shall the patent license extend to any additions 34 * to or modifications of the Original Intel Code. No other license or right 35 * is granted directly or by implication, estoppel or otherwise; 36 * 37 * The above copyright and patent license is granted only if the following 38 * conditions are met: 39 * 40 * 3. Conditions 41 * 42 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43 * Redistribution of source code of any substantial portion of the Covered 44 * Code or modification with rights to further distribute source must include 45 * the above Copyright Notice, the above License, this list of Conditions, 46 * and the following Disclaimer and Export Compliance provision. In addition, 47 * Licensee must cause all Covered Code to which Licensee contributes to 48 * contain a file documenting the changes Licensee made to create that Covered 49 * Code and the date of any change. Licensee must include in that file the 50 * documentation of any changes made by any predecessor Licensee. Licensee 51 * must include a prominent statement that the modification is derived, 52 * directly or indirectly, from Original Intel Code. 53 * 54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55 * Redistribution of source code of any substantial portion of the Covered 56 * Code or modification without rights to further distribute source must 57 * include the following Disclaimer and Export Compliance provision in the 58 * documentation and/or other materials provided with distribution. In 59 * addition, Licensee may not authorize further sublicense of source of any 60 * portion of the Covered Code, and must include terms to the effect that the 61 * license from Licensee to its licensee is limited to the intellectual 62 * property embodied in the software Licensee provides to its licensee, and 63 * not to intellectual property embodied in modifications its licensee may 64 * make. 65 * 66 * 3.3. Redistribution of Executable. Redistribution in executable form of any 67 * substantial portion of the Covered Code or modification must reproduce the 68 * above Copyright Notice, and the following Disclaimer and Export Compliance 69 * provision in the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3.4. Intel retains all right, title, and interest in and to the Original 73 * Intel Code. 74 * 75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76 * Intel shall be used in advertising or otherwise to promote the sale, use or 77 * other dealings in products derived from or relating to the Covered Code 78 * without prior written authorization from Intel. 79 * 80 * 4. Disclaimer and Export Compliance 81 * 82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88 * PARTICULAR PURPOSE. 89 * 90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97 * LIMITED REMEDY. 98 * 99 * 4.3. Licensee shall not export, either directly or indirectly, any of this 100 * software or system incorporating such software without first obtaining any 101 * required license or other approval from the U. S. Department of Commerce or 102 * any other agency or department of the United States Government. In the 103 * event Licensee exports any such software from the United States or 104 * re-exports any such software from a foreign destination, Licensee shall 105 * ensure that the distribution and export/re-export of the software is in 106 * compliance with all laws, regulations, orders, or other restrictions of the 107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108 * any of its subsidiaries will export/re-export any technical data, process, 109 * software, or service, directly or indirectly, to any country for which the 110 * United States government or any agency thereof requires an export license, 111 * other governmental approval, or letter of assurance, without first obtaining 112 * such license, approval or letter. 113 * 114 ***************************************************************************** 115 * 116 * Alternatively, you may choose to be licensed under the terms of the 117 * following license: 118 * 119 * Redistribution and use in source and binary forms, with or without 120 * modification, are permitted provided that the following conditions 121 * are met: 122 * 1. Redistributions of source code must retain the above copyright 123 * notice, this list of conditions, and the following disclaimer, 124 * without modification. 125 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 126 * substantially similar to the "NO WARRANTY" disclaimer below 127 * ("Disclaimer") and any redistribution must be conditioned upon 128 * including a substantially similar Disclaimer requirement for further 129 * binary redistribution. 130 * 3. Neither the names of the above-listed copyright holders nor the names 131 * of any contributors may be used to endorse or promote products derived 132 * from this software without specific prior written permission. 133 * 134 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 135 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 136 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 137 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 138 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 139 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 140 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 141 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 142 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 143 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 144 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 145 * 146 * Alternatively, you may choose to be licensed under the terms of the 147 * GNU General Public License ("GPL") version 2 as published by the Free 148 * Software Foundation. 149 * 150 *****************************************************************************/ 151 152 #include "acpi.h" 153 #include "accommon.h" 154 #include "acapps.h" 155 156 #define _COMPONENT ACPI_OS_SERVICES 157 ACPI_MODULE_NAME ("oseficlib") 158 159 160 /* Local definitions */ 161 162 #define ACPI_EFI_PRINT_LENGTH 256 163 164 #define ACPI_EFI_KEY_ESC 0x0000 165 #define ACPI_EFI_KEY_BACKSPACE 0x0008 166 #define ACPI_EFI_KEY_ENTER 0x000D 167 #define ACPI_EFI_KEY_CTRL_C 0x0003 168 169 #define ACPI_EFI_ASCII_NULL 0x00 170 #define ACPI_EFI_ASCII_DEL 0x7F 171 #define ACPI_EFI_ASCII_ESC 0x1B 172 #define ACPI_EFI_ASCII_CR '\r' 173 #define ACPI_EFI_ASCII_NL '\n' 174 175 176 /* Local prototypes */ 177 178 static int 179 AcpiEfiArgify ( 180 char *String, 181 int *ArgcPtr, 182 char ***ArgvPtr); 183 184 static int 185 AcpiEfiConvertArgcv ( 186 CHAR16 *LoadOpt, 187 UINT32 LoadOptSize, 188 int *ArgcPtr, 189 char ***ArgvPtr, 190 char **BufferPtr); 191 192 static int 193 AcpiEfiGetFileInfo ( 194 FILE *File, 195 ACPI_EFI_FILE_INFO **InfoPtr); 196 197 static CHAR16 * 198 AcpiEfiFlushFile ( 199 FILE *File, 200 CHAR16 *Begin, 201 CHAR16 *End, 202 CHAR16 *Pos, 203 BOOLEAN FlushAll); 204 205 206 /* Local variables */ 207 208 FILE *stdin = NULL; 209 FILE *stdout = NULL; 210 FILE *stderr = NULL; 211 static ACPI_EFI_FILE_HANDLE AcpiGbl_EfiCurrentVolume = NULL; 212 ACPI_EFI_GUID AcpiGbl_LoadedImageProtocol = ACPI_EFI_LOADED_IMAGE_PROTOCOL; 213 ACPI_EFI_GUID AcpiGbl_TextInProtocol = ACPI_SIMPLE_TEXT_INPUT_PROTOCOL; 214 ACPI_EFI_GUID AcpiGbl_TextOutProtocol = ACPI_SIMPLE_TEXT_OUTPUT_PROTOCOL; 215 ACPI_EFI_GUID AcpiGbl_FileSystemProtocol = ACPI_SIMPLE_FILE_SYSTEM_PROTOCOL; 216 ACPI_EFI_GUID AcpiGbl_GenericFileInfo = ACPI_EFI_FILE_INFO_ID; 217 218 int errno = 0; 219 220 221 /******************************************************************************* 222 * 223 * FUNCTION: fopen 224 * 225 * PARAMETERS: Path - File path 226 * Modes - File operation type 227 * 228 * RETURN: File descriptor 229 * 230 * DESCRIPTION: Open a file for reading or/and writing. 231 * 232 ******************************************************************************/ 233 234 FILE * 235 fopen ( 236 const char *Path, 237 const char *Modes) 238 { 239 ACPI_EFI_STATUS EfiStatus = ACPI_EFI_SUCCESS; 240 UINT64 OpenModes; 241 ACPI_EFI_FILE_HANDLE EfiFile = NULL; 242 CHAR16 *Path16 = NULL; 243 CHAR16 *Pos16; 244 const char *Pos; 245 INTN Count, i; 246 BOOLEAN IsAppend = FALSE; 247 FILE *File = NULL; 248 249 250 if (!Path) 251 { 252 errno = EINVAL; 253 return (NULL); 254 } 255 256 /* 257 * Convert modes, EFI says the only 2 read/write modes are read-only, 258 * read+write. Thus set default mode as read-only. 259 */ 260 OpenModes = ACPI_EFI_FILE_MODE_READ; 261 switch (*Modes++) 262 { 263 case 'r': 264 265 break; 266 267 case 'w': 268 269 OpenModes |= (ACPI_EFI_FILE_MODE_WRITE | ACPI_EFI_FILE_MODE_CREATE); 270 break; 271 272 case 'a': 273 274 OpenModes |= (ACPI_EFI_FILE_MODE_WRITE | ACPI_EFI_FILE_MODE_CREATE); 275 IsAppend = TRUE; 276 break; 277 278 default: 279 280 errno = EINVAL; 281 return (NULL); 282 } 283 284 for (; *Modes; Modes++) 285 { 286 switch (*Modes) 287 { 288 case '+': 289 290 OpenModes |= (ACPI_EFI_FILE_MODE_WRITE | ACPI_EFI_FILE_MODE_CREATE); 291 break; 292 293 case 'b': 294 case 't': 295 296 break; 297 298 case 'f': 299 default: 300 301 break; 302 } 303 } 304 305 /* Allocate path buffer */ 306 307 Count = strlen (Path); 308 Path16 = ACPI_ALLOCATE_ZEROED ((Count + 1) * sizeof (CHAR16)); 309 if (!Path16) 310 { 311 EfiStatus = ACPI_EFI_BAD_BUFFER_SIZE; 312 errno = ENOMEM; 313 goto ErrorExit; 314 } 315 Pos = Path; 316 Pos16 = Path16; 317 while (*Pos == '/' || *Pos == '\\') 318 { 319 Pos++; 320 Count--; 321 } 322 for (i = 0; i < Count; i++) 323 { 324 if (*Pos == '/') 325 { 326 *Pos16++ = '\\'; 327 Pos++; 328 } 329 else 330 { 331 *Pos16++ = *Pos++; 332 } 333 } 334 *Pos16 = '\0'; 335 336 EfiStatus = uefi_call_wrapper (AcpiGbl_EfiCurrentVolume->Open, 5, 337 AcpiGbl_EfiCurrentVolume, &EfiFile, Path16, OpenModes, 0); 338 if (ACPI_EFI_ERROR (EfiStatus)) 339 { 340 fprintf (stderr, "EFI_FILE_HANDLE->Open() failure.\n"); 341 errno = ENOENT; 342 goto ErrorExit; 343 } 344 345 File = (FILE *) EfiFile; 346 if (IsAppend) 347 { 348 fseek (File, 0, SEEK_END); 349 } 350 351 ErrorExit: 352 353 if (Path16) 354 { 355 ACPI_FREE (Path16); 356 } 357 358 return (File); 359 } 360 361 362 /******************************************************************************* 363 * 364 * FUNCTION: fclose 365 * 366 * PARAMETERS: File - File descriptor 367 * 368 * RETURN: None. 369 * 370 * DESCRIPTION: Close a file. 371 * 372 ******************************************************************************/ 373 374 void 375 fclose ( 376 FILE *File) 377 { 378 ACPI_EFI_FILE_HANDLE EfiFile; 379 380 381 if (File == stdin || File == stdout || 382 File == stderr) 383 { 384 return; 385 } 386 EfiFile = (ACPI_EFI_FILE_HANDLE) File; 387 (void) uefi_call_wrapper (AcpiGbl_EfiCurrentVolume->Close, 1, EfiFile); 388 389 return; 390 } 391 392 393 /******************************************************************************* 394 * 395 * FUNCTION: fgetc 396 * 397 * PARAMETERS: File - File descriptor 398 * 399 * RETURN: The character read or EOF on the end of the file or error 400 * 401 * DESCRIPTION: Read a character from the file. 402 * 403 ******************************************************************************/ 404 405 int 406 fgetc ( 407 FILE *File) 408 { 409 UINT8 Byte; 410 int Length; 411 412 413 Length = fread (ACPI_CAST_PTR (void, &Byte), 1, 1, File); 414 if (Length == 0) 415 { 416 Length = EOF; 417 } 418 else if (Length == 1) 419 { 420 Length = (int) Byte; 421 } 422 423 return (Length); 424 } 425 426 427 /******************************************************************************* 428 * 429 * FUNCTION: fputc 430 * 431 * PARAMETERS: File - File descriptor 432 * c - Character byte 433 * 434 * RETURN: The character written or EOF on the end of the file or error 435 * 436 * DESCRIPTION: Write a character to the file. 437 * 438 ******************************************************************************/ 439 440 int 441 fputc ( 442 FILE *File, 443 char c) 444 { 445 UINT8 Byte = (UINT8) c; 446 int Length; 447 448 449 Length = fwrite (ACPI_CAST_PTR (void, &Byte), 1, 1, File); 450 if (Length == 0) 451 { 452 Length = EOF; 453 } 454 else if (Length == 1) 455 { 456 Length = (int) Byte; 457 } 458 459 return (Length); 460 } 461 462 463 /******************************************************************************* 464 * 465 * FUNCTION: fgets 466 * 467 * PARAMETERS: File - File descriptor 468 * 469 * RETURN: The string read 470 * 471 * DESCRIPTION: Read a string from the file. 472 * 473 ******************************************************************************/ 474 475 char * 476 fgets ( 477 char *s, 478 ACPI_SIZE Size, 479 FILE *File) 480 { 481 ACPI_SIZE ReadBytes = 0; 482 int Ret; 483 484 485 if (Size <= 1) 486 { 487 errno = EINVAL; 488 return (NULL); 489 } 490 while (ReadBytes < (Size - 1)) 491 { 492 Ret = fgetc (File); 493 if (Ret == EOF) 494 { 495 if (ReadBytes == 0) 496 { 497 return (NULL); 498 } 499 break; 500 } 501 else if (Ret < 0) 502 { 503 errno = EIO; 504 return (NULL); 505 } 506 else if (Ret == '\n') 507 { 508 s[ReadBytes++] = (char) Ret; 509 break; 510 } 511 else 512 { 513 s[ReadBytes++] = (char) Ret; 514 } 515 } 516 517 s[ReadBytes] = '\0'; 518 return (s); 519 } 520 521 522 /******************************************************************************* 523 * 524 * FUNCTION: fread 525 * 526 * PARAMETERS: Buffer - Data buffer 527 * Size - Data block size 528 * Count - Number of data blocks 529 * File - File descriptor 530 * 531 * RETURN: Size of successfully read buffer 532 * 533 * DESCRIPTION: Read from a file. 534 * 535 ******************************************************************************/ 536 537 int 538 fread ( 539 void *Buffer, 540 ACPI_SIZE Size, 541 ACPI_SIZE Count, 542 FILE *File) 543 { 544 int Length = -EINVAL; 545 ACPI_EFI_FILE_HANDLE EfiFile; 546 ACPI_SIMPLE_INPUT_INTERFACE *In; 547 UINTN ReadSize; 548 ACPI_EFI_STATUS EfiStatus; 549 ACPI_EFI_INPUT_KEY Key; 550 ACPI_SIZE Pos = 0; 551 552 553 if (!Buffer) 554 { 555 errno = EINVAL; 556 goto ErrorExit; 557 } 558 559 ReadSize = Size * Count; 560 561 if (File == stdout || File == stderr) 562 { 563 /* Do not support read operations on output console */ 564 } 565 else if (File == stdin) 566 { 567 In = ACPI_CAST_PTR (ACPI_SIMPLE_INPUT_INTERFACE, File); 568 569 while (Pos < ReadSize) 570 { 571 WaitKey: 572 EfiStatus = uefi_call_wrapper (In->ReadKeyStroke, 2, In, &Key); 573 if (ACPI_EFI_ERROR (EfiStatus)) 574 { 575 if (EfiStatus == ACPI_EFI_NOT_READY) 576 { 577 goto WaitKey; 578 } 579 errno = EIO; 580 Length = -EIO; 581 fprintf (stderr, 582 "SIMPLE_INPUT_INTERFACE->ReadKeyStroke() failure.\n"); 583 goto ErrorExit; 584 } 585 586 switch (Key.UnicodeChar) 587 { 588 case ACPI_EFI_KEY_CTRL_C: 589 590 break; 591 592 case ACPI_EFI_KEY_ENTER: 593 594 *(ACPI_ADD_PTR (UINT8, Buffer, Pos)) = (UINT8) ACPI_EFI_ASCII_CR; 595 if (Pos < ReadSize - 1) 596 { 597 /* Drop CR in case we don't have sufficient buffer */ 598 599 Pos++; 600 } 601 *(ACPI_ADD_PTR (UINT8, Buffer, Pos)) = (UINT8) ACPI_EFI_ASCII_NL; 602 Pos++; 603 break; 604 605 case ACPI_EFI_KEY_BACKSPACE: 606 607 *(ACPI_ADD_PTR (UINT8, Buffer, Pos)) = (UINT8) ACPI_EFI_ASCII_DEL; 608 Pos++; 609 break; 610 611 case ACPI_EFI_KEY_ESC: 612 613 *(ACPI_ADD_PTR (UINT8, Buffer, Pos)) = (UINT8) ACPI_EFI_ASCII_ESC; 614 Pos++; 615 break; 616 617 default: 618 619 *(ACPI_ADD_PTR (UINT8, Buffer, Pos)) = (UINT8) Key.UnicodeChar; 620 Pos++; 621 break; 622 } 623 } 624 Length = (int) Pos; 625 } 626 else 627 { 628 EfiFile = (ACPI_EFI_FILE_HANDLE) File; 629 if (!EfiFile) 630 { 631 errno = EINVAL; 632 goto ErrorExit; 633 } 634 635 EfiStatus = uefi_call_wrapper (AcpiGbl_EfiCurrentVolume->Read, 3, 636 EfiFile, &ReadSize, Buffer); 637 if (ACPI_EFI_ERROR (EfiStatus)) 638 { 639 fprintf (stderr, "EFI_FILE_HANDLE->Read() failure.\n"); 640 errno = EIO; 641 Length = -EIO; 642 goto ErrorExit; 643 } 644 Length = (int) ReadSize; 645 } 646 647 ErrorExit: 648 649 return (Length); 650 } 651 652 653 /******************************************************************************* 654 * 655 * FUNCTION: AcpiEfiFlushFile 656 * 657 * PARAMETERS: File - File descriptor 658 * Begin - String with boundary 659 * End - Boundary of the string 660 * Pos - Current position 661 * FlushAll - Whether checking boundary before flushing 662 * 663 * RETURN: Updated position 664 * 665 * DESCRIPTION: Flush cached buffer to the file. 666 * 667 ******************************************************************************/ 668 669 static CHAR16 * 670 AcpiEfiFlushFile ( 671 FILE *File, 672 CHAR16 *Begin, 673 CHAR16 *End, 674 CHAR16 *Pos, 675 BOOLEAN FlushAll) 676 { 677 ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE *Out; 678 679 680 if (File == stdout || File == stderr) 681 { 682 Out = ACPI_CAST_PTR (ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE, File); 683 684 if (FlushAll || Pos >= (End - 1)) 685 { 686 *Pos = 0; 687 uefi_call_wrapper (Out->OutputString, 2, Out, Begin); 688 Pos = Begin; 689 } 690 } 691 692 return (Pos); 693 } 694 695 696 /******************************************************************************* 697 * 698 * FUNCTION: fwrite 699 * 700 * PARAMETERS: Buffer - Data buffer 701 * Size - Data block size 702 * Count - Number of data blocks 703 * File - File descriptor 704 * 705 * RETURN: Size of successfully written buffer 706 * 707 * DESCRIPTION: Write to a file. 708 * 709 ******************************************************************************/ 710 711 int 712 fwrite ( 713 void *Buffer, 714 ACPI_SIZE Size, 715 ACPI_SIZE Count, 716 FILE *File) 717 { 718 int Length = -EINVAL; 719 CHAR16 String[ACPI_EFI_PRINT_LENGTH]; 720 const char *Ascii; 721 CHAR16 *End; 722 CHAR16 *Pos; 723 ACPI_SIZE i, j; 724 ACPI_EFI_FILE_HANDLE EfiFile; 725 UINTN WriteSize; 726 ACPI_EFI_STATUS EfiStatus; 727 728 729 if (File == stdin) 730 { 731 /* Do not support write operations on input console */ 732 } 733 else if (File == stdout || File == stderr) 734 { 735 Pos = String; 736 End = String + ACPI_EFI_PRINT_LENGTH - 1; 737 Ascii = ACPI_CAST_PTR (const char, Buffer); 738 Length = 0; 739 740 for (j = 0; j < Count; j++) 741 { 742 for (i = 0; i < Size; i++) 743 { 744 if (*Ascii == '\n') 745 { 746 *Pos++ = '\r'; 747 Pos = AcpiEfiFlushFile (File, String, 748 End, Pos, FALSE); 749 } 750 *Pos++ = *Ascii++; 751 Length++; 752 Pos = AcpiEfiFlushFile (File, String, 753 End, Pos, FALSE); 754 } 755 } 756 Pos = AcpiEfiFlushFile (File, String, End, Pos, TRUE); 757 } 758 else 759 { 760 EfiFile = (ACPI_EFI_FILE_HANDLE) File; 761 if (!EfiFile) 762 { 763 errno = EINVAL; 764 goto ErrorExit; 765 } 766 WriteSize = Size * Count; 767 768 EfiStatus = uefi_call_wrapper (AcpiGbl_EfiCurrentVolume->Write, 3, 769 EfiFile, &WriteSize, Buffer); 770 if (ACPI_EFI_ERROR (EfiStatus)) 771 { 772 fprintf (stderr, "EFI_FILE_HANDLE->Write() failure.\n"); 773 errno = EIO; 774 goto ErrorExit; 775 } 776 Length = (int) WriteSize; 777 } 778 779 ErrorExit: 780 781 return (Length); 782 } 783 784 785 /******************************************************************************* 786 * 787 * FUNCTION: AcpiEfiGetFileInfo 788 * 789 * PARAMETERS: File - File descriptor 790 * InfoPtr - Pointer to contain file information 791 * 792 * RETURN: Clibrary error code 793 * 794 * DESCRIPTION: Get file information. 795 * 796 ******************************************************************************/ 797 798 static int 799 AcpiEfiGetFileInfo ( 800 FILE *File, 801 ACPI_EFI_FILE_INFO **InfoPtr) 802 { 803 ACPI_EFI_STATUS EfiStatus = ACPI_EFI_BUFFER_TOO_SMALL; 804 ACPI_EFI_FILE_INFO *Buffer = NULL; 805 UINTN BufferSize = SIZE_OF_ACPI_EFI_FILE_INFO + 200; 806 ACPI_EFI_FILE_HANDLE EfiFile; 807 808 809 if (!InfoPtr) 810 { 811 errno = EINVAL; 812 return (-EINVAL); 813 } 814 815 while (EfiStatus == ACPI_EFI_BUFFER_TOO_SMALL) 816 { 817 EfiFile = (ACPI_EFI_FILE_HANDLE) File; 818 Buffer = AcpiOsAllocate (BufferSize); 819 if (!Buffer) 820 { 821 errno = ENOMEM; 822 return (-ENOMEM); 823 } 824 EfiStatus = uefi_call_wrapper (EfiFile->GetInfo, 4, EfiFile, 825 &AcpiGbl_GenericFileInfo, &BufferSize, Buffer); 826 if (ACPI_EFI_ERROR (EfiStatus)) 827 { 828 AcpiOsFree (Buffer); 829 if (EfiStatus != ACPI_EFI_BUFFER_TOO_SMALL) 830 { 831 errno = EIO; 832 return (-EIO); 833 } 834 } 835 } 836 837 *InfoPtr = Buffer; 838 return (0); 839 } 840 841 842 /******************************************************************************* 843 * 844 * FUNCTION: ftell 845 * 846 * PARAMETERS: File - File descriptor 847 * 848 * RETURN: current position 849 * 850 * DESCRIPTION: Get current file offset. 851 * 852 ******************************************************************************/ 853 854 long 855 ftell ( 856 FILE *File) 857 { 858 long Offset = -1; 859 UINT64 Current; 860 ACPI_EFI_STATUS EfiStatus; 861 ACPI_EFI_FILE_HANDLE EfiFile; 862 863 864 if (File == stdin || File == stdout || File == stderr) 865 { 866 Offset = 0; 867 } 868 else 869 { 870 EfiFile = (ACPI_EFI_FILE_HANDLE) File; 871 872 EfiStatus = uefi_call_wrapper (EfiFile->GetPosition, 2, 873 EfiFile, &Current); 874 if (ACPI_EFI_ERROR (EfiStatus)) 875 { 876 goto ErrorExit; 877 } 878 else 879 { 880 Offset = (long) Current; 881 } 882 } 883 884 ErrorExit: 885 return (Offset); 886 } 887 888 889 /******************************************************************************* 890 * 891 * FUNCTION: fseek 892 * 893 * PARAMETERS: File - File descriptor 894 * Offset - File offset 895 * From - From begin/end of file 896 * 897 * RETURN: Status 898 * 899 * DESCRIPTION: Set current file offset. 900 * 901 ******************************************************************************/ 902 903 int 904 fseek ( 905 FILE *File, 906 long Offset, 907 int From) 908 { 909 ACPI_EFI_FILE_INFO *Info; 910 int Error; 911 ACPI_SIZE Size; 912 UINT64 Current; 913 ACPI_EFI_STATUS EfiStatus; 914 ACPI_EFI_FILE_HANDLE EfiFile; 915 916 917 if (File == stdin || File == stdout || File == stderr) 918 { 919 return (0); 920 } 921 else 922 { 923 EfiFile = (ACPI_EFI_FILE_HANDLE) File; 924 Error = AcpiEfiGetFileInfo (File, &Info); 925 if (Error) 926 { 927 return (Error); 928 } 929 Size = (ACPI_SIZE) (Info->FileSize); 930 AcpiOsFree (Info); 931 932 if (From == SEEK_CUR) 933 { 934 EfiStatus = uefi_call_wrapper (EfiFile->GetPosition, 2, 935 EfiFile, &Current); 936 if (ACPI_EFI_ERROR (EfiStatus)) 937 { 938 errno = ERANGE; 939 return (-ERANGE); 940 } 941 Current += Offset; 942 } 943 else if (From == SEEK_END) 944 { 945 Current = Size - Offset; 946 } 947 else 948 { 949 Current = Offset; 950 } 951 952 EfiStatus = uefi_call_wrapper (EfiFile->SetPosition, 2, 953 EfiFile, Current); 954 if (ACPI_EFI_ERROR (EfiStatus)) 955 { 956 errno = ERANGE; 957 return (-ERANGE); 958 } 959 } 960 961 return (0); 962 } 963 964 965 /****************************************************************************** 966 * 967 * FUNCTION: AcpiEfiArgify 968 * 969 * PARAMETERS: String - Pointer to command line argument strings 970 * which are separated with spaces 971 * ArgcPtr - Return number of the arguments 972 * ArgvPtr - Return vector of the arguments 973 * 974 * RETURN: Clibraray error code 975 * -EINVAL: invalid parameter 976 * EAGAIN: try again 977 * 978 * DESCRIPTION: Convert EFI arguments into C arguments. 979 * 980 *****************************************************************************/ 981 982 static int 983 AcpiEfiArgify ( 984 char *String, 985 int *ArgcPtr, 986 char ***ArgvPtr) 987 { 988 char *CopyBuffer; 989 int MaxArgc = *ArgcPtr; 990 int Argc = 0; 991 char **Argv = *ArgvPtr; 992 char *Arg; 993 BOOLEAN IsSingleQuote = FALSE; 994 BOOLEAN IsDoubleQuote = FALSE; 995 BOOLEAN IsEscape = FALSE; 996 997 998 if (String == NULL) 999 { 1000 errno = EINVAL; 1001 return (-EINVAL); 1002 } 1003 1004 CopyBuffer = String; 1005 1006 while (*String != '\0') 1007 { 1008 while (isspace (*String)) 1009 { 1010 *String++ = '\0'; 1011 } 1012 Arg = CopyBuffer; 1013 while (*String != '\0') 1014 { 1015 if (isspace (*String) && 1016 !IsSingleQuote && !IsDoubleQuote && !IsEscape) 1017 { 1018 *Arg++ = '\0'; 1019 String++; 1020 break; 1021 } 1022 if (IsEscape) 1023 { 1024 IsEscape = FALSE; 1025 *Arg++ = *String; 1026 } 1027 else if (*String == '\\') 1028 { 1029 IsEscape = TRUE; 1030 } 1031 else if (IsSingleQuote) 1032 { 1033 if (*String == '\'') 1034 { 1035 IsSingleQuote = FALSE; 1036 *Arg++ = '\0'; 1037 } 1038 else 1039 { 1040 *Arg++ = *String; 1041 } 1042 } 1043 else if (IsDoubleQuote) 1044 { 1045 if (*String == '"') 1046 { 1047 IsDoubleQuote = FALSE; 1048 *Arg = '\0'; 1049 } 1050 else 1051 { 1052 *Arg++ = *String; 1053 } 1054 } 1055 else 1056 { 1057 if (*String == '\'') 1058 { 1059 IsSingleQuote = TRUE; 1060 } 1061 else if (*String == '"') 1062 { 1063 IsDoubleQuote = TRUE; 1064 } 1065 else 1066 { 1067 *Arg++ = *String; 1068 } 1069 } 1070 String++; 1071 } 1072 if (Argv && Argc < MaxArgc) 1073 { 1074 Argv[Argc] = CopyBuffer; 1075 } 1076 Argc++; 1077 CopyBuffer = Arg; 1078 } 1079 if (Argv && Argc < MaxArgc) 1080 { 1081 Argv[Argc] = NULL; 1082 } 1083 1084 *ArgcPtr = Argc; 1085 *ArgvPtr = Argv; 1086 1087 if (MaxArgc < Argc) 1088 { 1089 errno = EAGAIN; 1090 return (-ENOMEM); 1091 } 1092 return (0); 1093 } 1094 1095 1096 /****************************************************************************** 1097 * 1098 * FUNCTION: AcpiEfiConvertArgcv 1099 * 1100 * PARAMETERS: LoadOptions - Pointer to the EFI options buffer, which 1101 * is NULL terminated 1102 * LoadOptionsSize - Size of the EFI options buffer 1103 * ArgcPtr - Return number of the arguments 1104 * ArgvPtr - Return vector of the arguments 1105 * BufferPtr - Buffer to contain the argument strings 1106 * 1107 * RETURN: Clibrary error code 1108 * 1109 * DESCRIPTION: Convert EFI arguments into C arguments. 1110 * 1111 *****************************************************************************/ 1112 1113 static int 1114 AcpiEfiConvertArgcv ( 1115 CHAR16 *LoadOptions, 1116 UINT32 LoadOptionsSize, 1117 int *ArgcPtr, 1118 char ***ArgvPtr, 1119 char **BufferPtr) 1120 { 1121 int Error = 0; 1122 UINT32 Count = LoadOptionsSize / sizeof (CHAR16); 1123 UINT32 i; 1124 CHAR16 *From; 1125 char *To; 1126 int Argc = 0; 1127 char **Argv = NULL; 1128 char *Buffer; 1129 1130 1131 /* Prepare a buffer to contain the argument strings */ 1132 1133 Buffer = ACPI_ALLOCATE_ZEROED (Count); 1134 if (!Buffer) 1135 { 1136 errno = ENOMEM; 1137 Error = -ENOMEM; 1138 goto ErrorExit; 1139 } 1140 1141 TryAgain: 1142 1143 /* Extend the argument vector */ 1144 1145 if (Argv) 1146 { 1147 ACPI_FREE (Argv); 1148 Argv = NULL; 1149 } 1150 if (Argc > 0) 1151 { 1152 Argv = ACPI_ALLOCATE_ZEROED (sizeof (char *) * (Argc + 1)); 1153 if (!Argv) 1154 { 1155 errno = ENOMEM; 1156 Error = -ENOMEM; 1157 goto ErrorExit; 1158 } 1159 } 1160 1161 /* 1162 * Note: As AcpiEfiArgify() will modify the content of the buffer, so 1163 * we need to restore it each time before invoking 1164 * AcpiEfiArgify(). 1165 */ 1166 From = LoadOptions; 1167 To = ACPI_CAST_PTR (char, Buffer); 1168 for (i = 0; i < Count; i++) 1169 { 1170 *To++ = (char) *From++; 1171 } 1172 1173 /* 1174 * The "Buffer" will contain NULL terminated strings after invoking 1175 * AcpiEfiArgify(). The number of the strings are saved in Argc and the 1176 * pointers of the strings are saved in Argv. 1177 */ 1178 Error = AcpiEfiArgify (Buffer, &Argc, &Argv); 1179 if (Error && errno == EAGAIN) 1180 { 1181 goto TryAgain; 1182 } 1183 1184 ErrorExit: 1185 1186 if (Error) 1187 { 1188 ACPI_FREE (Buffer); 1189 ACPI_FREE (Argv); 1190 } 1191 else 1192 { 1193 *ArgcPtr = Argc; 1194 *ArgvPtr = Argv; 1195 *BufferPtr = Buffer; 1196 } 1197 return (Error); 1198 } 1199 1200 1201 /****************************************************************************** 1202 * 1203 * FUNCTION: efi_main 1204 * 1205 * PARAMETERS: Image - EFI image handle 1206 * SystemTab - EFI system table 1207 * 1208 * RETURN: EFI Status 1209 * 1210 * DESCRIPTION: Entry point of EFI executable 1211 * 1212 *****************************************************************************/ 1213 1214 ACPI_EFI_STATUS 1215 efi_main ( 1216 ACPI_EFI_HANDLE Image, 1217 ACPI_EFI_SYSTEM_TABLE *SystemTab) 1218 { 1219 ACPI_EFI_LOADED_IMAGE *Info; 1220 ACPI_EFI_STATUS EfiStatus = ACPI_EFI_SUCCESS; 1221 int Error; 1222 int argc; 1223 char **argv = NULL; 1224 char *OptBuffer = NULL; 1225 ACPI_EFI_FILE_IO_INTERFACE *Volume = NULL; 1226 1227 1228 /* Initialize global variables */ 1229 1230 ST = SystemTab; 1231 BS = SystemTab->BootServices; 1232 RT = SystemTab->RuntimeServices; 1233 stdin = ACPI_CAST_PTR (ACPI_EFI_FILE, SystemTab->ConIn); 1234 stdout = ACPI_CAST_PTR (ACPI_EFI_FILE, SystemTab->ConOut); 1235 stderr = ACPI_CAST_PTR (ACPI_EFI_FILE, SystemTab->ConOut); 1236 1237 /* Disable the platform watchdog timer if we go interactive */ 1238 1239 uefi_call_wrapper(BS->SetWatchdogTimer, 4, 0, 0x0, 0, NULL); 1240 1241 /* Retrieve image information */ 1242 1243 EfiStatus = uefi_call_wrapper (BS->HandleProtocol, 3, 1244 Image, &AcpiGbl_LoadedImageProtocol, ACPI_CAST_PTR (VOID, &Info)); 1245 if (ACPI_EFI_ERROR (EfiStatus)) 1246 { 1247 fprintf (stderr, 1248 "EFI_BOOT_SERVICES->HandleProtocol(LoadedImageProtocol) failure.\n"); 1249 return (EfiStatus); 1250 } 1251 1252 EfiStatus = uefi_call_wrapper (BS->HandleProtocol, 3, 1253 Info->DeviceHandle, &AcpiGbl_FileSystemProtocol, (void **) &Volume); 1254 if (ACPI_EFI_ERROR (EfiStatus)) 1255 { 1256 fprintf (stderr, 1257 "EFI_BOOT_SERVICES->HandleProtocol(FileSystemProtocol) failure.\n"); 1258 return (EfiStatus); 1259 } 1260 EfiStatus = uefi_call_wrapper (Volume->OpenVolume, 2, 1261 Volume, &AcpiGbl_EfiCurrentVolume); 1262 if (ACPI_EFI_ERROR (EfiStatus)) 1263 { 1264 fprintf (stderr, "EFI_FILE_IO_INTERFACE->OpenVolume() failure.\n"); 1265 return (EfiStatus); 1266 } 1267 1268 Error = AcpiEfiConvertArgcv (Info->LoadOptions, 1269 Info->LoadOptionsSize, &argc, &argv, &OptBuffer); 1270 if (Error) 1271 { 1272 EfiStatus = ACPI_EFI_DEVICE_ERROR; 1273 goto ErrorAlloc; 1274 } 1275 1276 acpi_main (argc, argv); 1277 1278 ErrorAlloc: 1279 1280 if (argv) 1281 { 1282 ACPI_FREE (argv); 1283 } 1284 if (OptBuffer) 1285 { 1286 ACPI_FREE (OptBuffer); 1287 } 1288 1289 return (EfiStatus); 1290 } 1291 1292 #ifdef _EDK2_EFI 1293 EFI_STATUS 1294 EFIAPI 1295 UefiMain ( 1296 EFI_HANDLE Image, 1297 EFI_SYSTEM_TABLE *SystemTab) 1298 { 1299 EFI_STATUS EfiStatus; 1300 1301 1302 EfiStatus = (EFI_STATUS) efi_main ( 1303 (ACPI_EFI_HANDLE) Image, (ACPI_EFI_SYSTEM_TABLE *) SystemTab); 1304 return (EfiStatus); 1305 } 1306 #endif 1307