]> git.proxmox.com Git - mirror_edk2.git/blob - StdLib/LibC/Main/Main.c
Add Socket Libraries.
[mirror_edk2.git] / StdLib / LibC / Main / Main.c
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 <MainData.h>
31 #include <sys/EfiSysCall.h>
32
33 extern int main( int, char**);
34 extern int __sse2_available;
35
36 struct __MainData *gMD;
37
38 /* Worker function to keep GCC happy. */
39 void __main()
40 {
41 ;
42 }
43
44 /** Clean up data as required by the exit() function.
45
46 **/
47 void
48 exitCleanup(INTN ExitVal)
49 {
50 void (*CleanUp)(void); // Pointer to Cleanup Function
51 int i;
52
53 if(gMD != NULL) {
54 gMD->ExitValue = (int)ExitVal;
55 CleanUp = gMD->cleanup; // Preserve the pointer to the Cleanup Function
56
57 // Call all registered atexit functions in reverse order
58 i = gMD->num_atexit;
59 if( i > 0) {
60 do {
61 (gMD->atexit_handler[--i])();
62 } while( i > 0);
63 }
64
65 if (CleanUp != NULL) {
66 CleanUp();
67 }
68 }
69 }
70
71 /* Create mbcs versions of the Argv strings. */
72 static
73 char **
74 ArgvConvert(UINTN Argc, CHAR16 **Argv)
75 {
76 size_t AVsz; /* Size of a single nArgv string */
77 UINTN count;
78 char **nArgv;
79 char *string;
80 INTN nArgvSize; /* Cumulative size of narrow Argv[i] */
81
82 DEBUG_CODE_BEGIN();
83 Print(L"ArgvConvert called with %d arguments.\n", Argc);
84 for(count = 0; count < ((Argc > 5)? 5: Argc); ++count) {
85 Print(L"Argument[%d] = \"%s\".\n", count, Argv[count]);
86 }
87 DEBUG_CODE_END();
88
89 nArgvSize = Argc;
90 /* Determine space needed for narrow Argv strings. */
91 for(count = 0; count < Argc; ++count) {
92 AVsz = wcstombs(NULL, Argv[count], ARG_MAX);
93 if(AVsz < 0) {
94 Print(L"ABORTING: Argv[%d] contains an unconvertable character.\n", count);
95 exit(EXIT_FAILURE);
96 /* Not Reached */
97 }
98 nArgvSize += AVsz;
99 }
100
101 /* Reserve space for the converted strings. */
102 gMD->NCmdLine = (char *)AllocateZeroPool(nArgvSize+1);
103 if(gMD->NCmdLine == NULL) {
104 Print(L"ABORTING: Insufficient memory.\n");
105 exit(EXIT_FAILURE);
106 /* Not Reached */
107 }
108
109 /* Convert Argument Strings. */
110 nArgv = gMD->NArgV;
111 string = gMD->NCmdLine;
112 for(count = 0; count < Argc; ++count) {
113 nArgv[count] = string;
114 AVsz = wcstombs(string, Argv[count], nArgvSize);
115 string[AVsz] = 0; /* NULL terminate the argument */
116 DEBUG((DEBUG_INFO, "Cvt[%d] %d \"%s\" --> \"%a\"\n", (INT32)count, (INT32)AVsz, Argv[count], nArgv[count]));
117 string += AVsz + 1;
118 nArgvSize -= AVsz + 1;
119 if(nArgvSize < 0) {
120 Print(L"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 #ifdef NT32dvm
153 gMD->ClocksPerSecond = 1; // For NT32 only
154 gMD->AppStartTime = 1; // For NT32 only
155 #else
156 gMD->ClocksPerSecond = (clock_t)GetPerformanceCounterProperties( NULL, NULL);
157 gMD->AppStartTime = (clock_t)GetPerformanceCounter();
158 #endif /* NT32 dvm */
159
160 // Initialize file descriptors
161 mfd = gMD->fdarray;
162 for(i = 0; i < (FOPEN_MAX); ++i) {
163 mfd[i].MyFD = (UINT16)i;
164 }
165
166 i = open("stdin:", O_RDONLY, 0444);
167 if(i == 0) {
168 i = open("stdout:", O_WRONLY, 0222);
169 if(i == 1) {
170 i = open("stderr:", O_WRONLY, 0222);
171 }
172 }
173 if(i != 2) {
174 Print(L"ERROR Initializing Standard IO: %a.\n %r\n",
175 strerror(errno), EFIerrno);
176 }
177
178 /* Create mbcs versions of the Argv strings. */
179 nArgv = ArgvConvert(Argc, Argv);
180 if(nArgv == NULL) {
181 ExitVal = (INTN)RETURN_INVALID_PARAMETER;
182 }
183 else {
184 if( setjmp(gMD->MainExit) == 0) {
185 ExitVal = (INTN)main( (int)Argc, gMD->NArgV);
186 exitCleanup(ExitVal);
187 }
188 /* You reach here if:
189 * normal return from main()
190 * call to _Exit(), either directly or through exit().
191 */
192 ExitVal = (INTN)gMD->ExitValue;
193 }
194
195 if( ExitVal == EXIT_FAILURE) {
196 ExitVal = RETURN_ABORTED;
197 }
198
199 /* Close any open files */
200 for(i = OPEN_MAX - 1; i >= 0; --i) {
201 (void)close(i); // Close properly handles closing a closed file.
202 }
203
204 /* Free the global MainData structure */
205 if(gMD != NULL) {
206 if(gMD->NCmdLine != NULL) {
207 FreePool( gMD->NCmdLine );
208 }
209 FreePool( gMD );
210 }
211 }
212 return ExitVal;
213 }