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