Vishal Bhoj | 82c8071 | 2015-12-15 21:13:33 +0530 | [diff] [blame] | 1 | /** @file
|
| 2 | Establish the program environment and the "main" entry point.
|
| 3 |
|
| 4 | All of the global data in the gMD structure is initialized to 0, NULL, or
|
| 5 | SIG_DFL; as appropriate.
|
| 6 |
|
| 7 | Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
|
| 8 | This program and the accompanying materials are licensed and made available under
|
| 9 | the terms and conditions of the BSD License that accompanies this distribution.
|
| 10 | The full text of the license may be found at
|
| 11 | http://opensource.org/licenses/bsd-license.
|
| 12 |
|
| 13 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
| 14 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
| 15 | **/
|
| 16 | #include <Uefi.h>
|
| 17 | #include <Library/UefiLib.h>
|
| 18 | #include <Library/DebugLib.h>
|
| 19 |
|
| 20 | #include <Library/ShellCEntryLib.h>
|
| 21 | #include <Library/MemoryAllocationLib.h>
|
| 22 | #include <Library/TimerLib.h>
|
| 23 |
|
| 24 | #include <LibConfig.h>
|
| 25 |
|
| 26 | #include <errno.h>
|
| 27 | #include <stdio.h>
|
| 28 | #include <stdlib.h>
|
| 29 | #include <string.h>
|
| 30 | #include <time.h>
|
| 31 | #include <MainData.h>
|
| 32 | #include <unistd.h>
|
| 33 |
|
| 34 | extern int main( int, char**);
|
| 35 | extern int __sse2_available;
|
| 36 |
|
| 37 | struct __MainData *gMD;
|
| 38 |
|
| 39 | /* Worker function to keep GCC happy. */
|
| 40 | void __main()
|
| 41 | {
|
| 42 | ;
|
| 43 | }
|
| 44 |
|
| 45 | /** Clean up data as required by the exit() function.
|
| 46 |
|
| 47 | **/
|
| 48 | void
|
| 49 | exitCleanup(INTN ExitVal)
|
| 50 | {
|
| 51 | void (*CleanUp)(void); // Pointer to Cleanup Function
|
| 52 | int i;
|
| 53 |
|
| 54 | if(gMD != NULL) {
|
| 55 | gMD->ExitValue = (int)ExitVal;
|
| 56 | CleanUp = gMD->cleanup; // Preserve the pointer to the Cleanup Function
|
| 57 |
|
| 58 | // Call all registered atexit functions in reverse order
|
| 59 | i = gMD->num_atexit;
|
| 60 | if( i > 0) {
|
| 61 | do {
|
| 62 | (gMD->atexit_handler[--i])();
|
| 63 | } while( i > 0);
|
| 64 | }
|
| 65 |
|
| 66 | if (CleanUp != NULL) {
|
| 67 | CleanUp();
|
| 68 | }
|
| 69 | }
|
| 70 | }
|
| 71 |
|
| 72 | /* Create mbcs versions of the Argv strings. */
|
| 73 | static
|
| 74 | char **
|
| 75 | ArgvConvert(UINTN Argc, CHAR16 **Argv)
|
| 76 | {
|
| 77 | ssize_t AVsz; /* Size of a single nArgv string, or -1 */
|
| 78 | UINTN count;
|
| 79 | char **nArgv;
|
| 80 | char *string;
|
| 81 | INTN nArgvSize; /* Cumulative size of narrow Argv[i] */
|
| 82 |
|
| 83 | DEBUG_CODE_BEGIN();
|
| 84 | DEBUG((DEBUG_INIT, "ArgvConvert called with %d arguments.\n", Argc));
|
| 85 | for(count = 0; count < ((Argc > 5)? 5: Argc); ++count) {
|
| 86 | DEBUG((DEBUG_INIT, "Argument[%d] = \"%s\".\n", count, Argv[count]));
|
| 87 | }
|
| 88 | DEBUG_CODE_END();
|
| 89 |
|
| 90 | nArgvSize = Argc;
|
| 91 | /* Determine space needed for narrow Argv strings. */
|
| 92 | for(count = 0; count < Argc; ++count) {
|
| 93 | AVsz = (ssize_t)wcstombs(NULL, Argv[count], ARG_MAX);
|
| 94 | if(AVsz < 0) {
|
| 95 | DEBUG((DEBUG_ERROR, "ABORTING: Argv[%d] contains an unconvertable character.\n", count));
|
| 96 | exit(EXIT_FAILURE);
|
| 97 | /* Not Reached */
|
| 98 | }
|
| 99 | nArgvSize += AVsz;
|
| 100 | }
|
| 101 |
|
| 102 | /* Reserve space for the converted strings. */
|
| 103 | gMD->NCmdLine = (char *)AllocateZeroPool(nArgvSize+1);
|
| 104 | if(gMD->NCmdLine == NULL) {
|
| 105 | DEBUG((DEBUG_ERROR, "ABORTING: Insufficient memory.\n"));
|
| 106 | exit(EXIT_FAILURE);
|
| 107 | /* Not Reached */
|
| 108 | }
|
| 109 |
|
| 110 | /* Convert Argument Strings. */
|
| 111 | nArgv = gMD->NArgV;
|
| 112 | string = gMD->NCmdLine;
|
| 113 | for(count = 0; count < Argc; ++count) {
|
| 114 | nArgv[count] = string;
|
| 115 | AVsz = wcstombs(string, Argv[count], nArgvSize) + 1;
|
| 116 | DEBUG((DEBUG_INFO, "Cvt[%d] %d \"%s\" --> \"%a\"\n", (INT32)count, (INT32)AVsz, Argv[count], nArgv[count]));
|
| 117 | string += AVsz;
|
| 118 | nArgvSize -= AVsz;
|
| 119 | if(nArgvSize < 0) {
|
| 120 | DEBUG((DEBUG_ERROR, "ABORTING: Internal Argv[%d] conversion error.\n", count));
|
| 121 | exit(EXIT_FAILURE);
|
| 122 | /* Not Reached */
|
| 123 | }
|
| 124 | }
|
| 125 | return gMD->NArgV;
|
| 126 | }
|
| 127 |
|
| 128 | INTN
|
| 129 | EFIAPI
|
| 130 | ShellAppMain (
|
| 131 | IN UINTN Argc,
|
| 132 | IN CHAR16 **Argv
|
| 133 | )
|
| 134 | {
|
| 135 | struct __filedes *mfd;
|
| 136 | char **nArgv;
|
| 137 | INTN ExitVal;
|
| 138 | int i;
|
| 139 |
|
| 140 | ExitVal = (INTN)RETURN_SUCCESS;
|
| 141 | gMD = AllocateZeroPool(sizeof(struct __MainData));
|
| 142 | if( gMD == NULL ) {
|
| 143 | ExitVal = (INTN)RETURN_OUT_OF_RESOURCES;
|
| 144 | }
|
| 145 | else {
|
| 146 | /* Initialize data */
|
| 147 | __sse2_available = 0;
|
| 148 | _fltused = 1;
|
| 149 | errno = 0;
|
| 150 | EFIerrno = 0;
|
| 151 |
|
| 152 | gMD->ClocksPerSecond = 1;
|
| 153 | gMD->AppStartTime = (clock_t)((UINT32)time(NULL));
|
| 154 |
|
| 155 | // Initialize file descriptors
|
| 156 | mfd = gMD->fdarray;
|
| 157 | for(i = 0; i < (FOPEN_MAX); ++i) {
|
| 158 | mfd[i].MyFD = (UINT16)i;
|
| 159 | }
|
| 160 |
|
| 161 | DEBUG((DEBUG_INIT, "StdLib: Open Standard IO.\n"));
|
| 162 | i = open("stdin:", (O_RDONLY | O_TTY_INIT), 0444);
|
| 163 | if(i == 0) {
|
| 164 | i = open("stdout:", (O_WRONLY | O_TTY_INIT), 0222);
|
| 165 | if(i == 1) {
|
| 166 | i = open("stderr:", O_WRONLY, 0222);
|
| 167 | }
|
| 168 | }
|
| 169 | if(i != 2) {
|
| 170 | Print(L"ERROR Initializing Standard IO: %a.\n %r\n",
|
| 171 | strerror(errno), EFIerrno);
|
| 172 | }
|
| 173 |
|
| 174 | /* Create mbcs versions of the Argv strings. */
|
| 175 | nArgv = ArgvConvert(Argc, Argv);
|
| 176 | if(nArgv == NULL) {
|
| 177 | ExitVal = (INTN)RETURN_INVALID_PARAMETER;
|
| 178 | }
|
| 179 | else {
|
| 180 | if( setjmp(gMD->MainExit) == 0) {
|
| 181 | errno = 0; // Clean up any "scratch" values from startup.
|
| 182 | ExitVal = (INTN)main( (int)Argc, gMD->NArgV);
|
| 183 | exitCleanup(ExitVal);
|
| 184 | }
|
| 185 | /* You reach here if:
|
| 186 | * normal return from main()
|
| 187 | * call to _Exit(), either directly or through exit().
|
| 188 | */
|
| 189 | ExitVal = (INTN)gMD->ExitValue;
|
| 190 | }
|
| 191 |
|
| 192 | if( ExitVal == EXIT_FAILURE) {
|
| 193 | ExitVal = RETURN_ABORTED;
|
| 194 | }
|
| 195 |
|
| 196 | /* Close any open files */
|
| 197 | for(i = OPEN_MAX - 1; i >= 0; --i) {
|
| 198 | (void)close(i); // Close properly handles closing a closed file.
|
| 199 | }
|
| 200 |
|
| 201 | /* Free the global MainData structure */
|
| 202 | if(gMD != NULL) {
|
| 203 | if(gMD->NCmdLine != NULL) {
|
| 204 | FreePool( gMD->NCmdLine );
|
| 205 | }
|
| 206 | FreePool( gMD );
|
| 207 | }
|
| 208 | }
|
| 209 | return ExitVal;
|
| 210 | }
|