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 - 2011, 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 | size_t AVsz; /* Size of a single nArgv string */
|
---|
78 | UINTN count;
|
---|
79 | char **nArgv;
|
---|
80 | char *string;
|
---|
81 | INTN nArgvSize; /* Cumulative size of narrow Argv[i] */
|
---|
82 |
|
---|
83 | DEBUG_CODE_BEGIN();
|
---|
84 | Print(L"ArgvConvert called with %d arguments.\n", Argc);
|
---|
85 | for(count = 0; count < ((Argc > 5)? 5: Argc); ++count) {
|
---|
86 | Print(L"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 = wcstombs(NULL, Argv[count], ARG_MAX);
|
---|
94 | if(AVsz < 0) {
|
---|
95 | Print(L"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 | Print(L"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);
|
---|
116 | string[AVsz] = 0; /* NULL terminate the argument */
|
---|
117 | DEBUG((DEBUG_INFO, "Cvt[%d] %d \"%s\" --> \"%a\"\n", (INT32)count, (INT32)AVsz, Argv[count], nArgv[count]));
|
---|
118 | string += AVsz + 1;
|
---|
119 | nArgvSize -= AVsz + 1;
|
---|
120 | if(nArgvSize < 0) {
|
---|
121 | Print(L"ABORTING: Internal Argv[%d] conversion error.\n", count);
|
---|
122 | exit(EXIT_FAILURE);
|
---|
123 | /* Not Reached */
|
---|
124 | }
|
---|
125 | }
|
---|
126 | return gMD->NArgV;
|
---|
127 | }
|
---|
128 |
|
---|
129 | INTN
|
---|
130 | EFIAPI
|
---|
131 | ShellAppMain (
|
---|
132 | IN UINTN Argc,
|
---|
133 | IN CHAR16 **Argv
|
---|
134 | )
|
---|
135 | {
|
---|
136 | struct __filedes *mfd;
|
---|
137 | char **nArgv;
|
---|
138 | INTN ExitVal;
|
---|
139 | int i;
|
---|
140 |
|
---|
141 | ExitVal = (INTN)RETURN_SUCCESS;
|
---|
142 | gMD = AllocateZeroPool(sizeof(struct __MainData));
|
---|
143 | if( gMD == NULL ) {
|
---|
144 | ExitVal = (INTN)RETURN_OUT_OF_RESOURCES;
|
---|
145 | }
|
---|
146 | else {
|
---|
147 | /* Initialize data */
|
---|
148 | __sse2_available = 0;
|
---|
149 | _fltused = 1;
|
---|
150 | errno = 0;
|
---|
151 | EFIerrno = 0;
|
---|
152 |
|
---|
153 | gMD->ClocksPerSecond = 1;
|
---|
154 | gMD->AppStartTime = (clock_t)((UINT32)time(NULL));
|
---|
155 |
|
---|
156 | // Initialize file descriptors
|
---|
157 | mfd = gMD->fdarray;
|
---|
158 | for(i = 0; i < (FOPEN_MAX); ++i) {
|
---|
159 | mfd[i].MyFD = (UINT16)i;
|
---|
160 | }
|
---|
161 |
|
---|
162 | i = open("stdin:", O_RDONLY, 0444);
|
---|
163 | if(i == 0) {
|
---|
164 | i = open("stdout:", O_WRONLY, 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 | ExitVal = (INTN)main( (int)Argc, gMD->NArgV);
|
---|
182 | exitCleanup(ExitVal);
|
---|
183 | }
|
---|
184 | /* You reach here if:
|
---|
185 | * normal return from main()
|
---|
186 | * call to _Exit(), either directly or through exit().
|
---|
187 | */
|
---|
188 | ExitVal = (INTN)gMD->ExitValue;
|
---|
189 | }
|
---|
190 |
|
---|
191 | if( ExitVal == EXIT_FAILURE) {
|
---|
192 | ExitVal = RETURN_ABORTED;
|
---|
193 | }
|
---|
194 |
|
---|
195 | /* Close any open files */
|
---|
196 | for(i = OPEN_MAX - 1; i >= 0; --i) {
|
---|
197 | (void)close(i); // Close properly handles closing a closed file.
|
---|
198 | }
|
---|
199 |
|
---|
200 | /* Free the global MainData structure */
|
---|
201 | if(gMD != NULL) {
|
---|
202 | if(gMD->NCmdLine != NULL) {
|
---|
203 | FreePool( gMD->NCmdLine );
|
---|
204 | }
|
---|
205 | FreePool( gMD );
|
---|
206 | }
|
---|
207 | }
|
---|
208 | return ExitVal;
|
---|
209 | }
|
---|