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