]> git.proxmox.com Git - mirror_edk2.git/blame - StdLib/LibC/Main/Main.c
Changes so that Argv points to narrow-character versions of the command-line arguments.
[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
11 http://opensource.org/licenses/bsd-license.php.\r
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
18\r
19#include <Library/ShellCEntryLib.h>\r
20#include <Library/MemoryAllocationLib.h>\r
21#include <Library/TimerLib.h>\r
22\r
23#include <LibConfig.h>\r
24\r
25#include <errno.h>\r
26#include <stdio.h>\r
53e1e5c6 27#include <stdlib.h>\r
2aa62f2b 28#include <string.h>\r
29#include <MainData.h>\r
53e1e5c6 30#include <sys/EfiSysCall.h>\r
2aa62f2b 31\r
53e1e5c6 32extern int main( int, char**);\r
2aa62f2b 33extern int __sse2_available;\r
34\r
35struct __MainData *gMD;\r
36\r
37/* Worker function to keep GCC happy. */\r
38void __main()\r
39{\r
40 ;\r
41}\r
42\r
53e1e5c6 43static\r
44void\r
45FinalCleanup( void )\r
46{\r
47 int i;\r
48\r
49 /* Close any open files */\r
50 for(i = OPEN_MAX - 1; i >= 0; --i) {\r
51 (void)close(i); // Close properly handles closing a closed file.\r
52 }\r
53\r
54 /* Free the global MainData structure */\r
55 if(gMD != NULL) {\r
56 if(gMD->NCmdLine != NULL) {\r
57 FreePool( gMD->NCmdLine );\r
58 }\r
59 FreePool( gMD );\r
60 }\r
61}\r
62\r
63/* Create mbcs versions of the Argv strings. */\r
64static\r
65char **\r
66ArgvConvert(UINTN Argc, CHAR16 **Argv)\r
67{\r
68 size_t AVsz; /* Size of a single nArgv string */\r
69 UINTN count;\r
70 char **nArgv;\r
71 char *string;\r
72 INTN nArgvSize; /* Cumulative size of narrow Argv[i] */\r
73\r
74 nArgvSize = Argc;\r
75 /* Determine space needed for narrow Argv strings. */\r
76 for(count = 0; count < Argc; ++count) {\r
77 AVsz = wcstombs(NULL, Argv[count], ARG_MAX);\r
78 if(AVsz < 0) {\r
79 Print(L"ABORTING: Argv[%d] contains an unconvertable character.\n", count);\r
80 exit(EXIT_FAILURE);\r
81 /* Not Reached */\r
82 }\r
83 nArgvSize += AVsz;\r
84 }\r
85\r
86 /* Reserve space for the converted strings. */\r
87 gMD->NCmdLine = (char *)AllocateZeroPool(nArgvSize+1);\r
88 if(gMD->NCmdLine == NULL) {\r
89 Print(L"ABORTING: Insufficient memory.\n");\r
90 exit(EXIT_FAILURE);\r
91 /* Not Reached */\r
92 }\r
93\r
94 /* Convert Argument Strings. */\r
95 nArgv = gMD->NArgV;\r
96 string = gMD->NCmdLine;\r
97 for(count = 0; count < Argc; ++count) {\r
98 nArgv[count] = string;\r
99 AVsz = wcstombs(string, Argv[count], nArgvSize);\r
100 string[AVsz] = 0; /* NULL terminate the argument */\r
101 string += AVsz + 1;\r
102 nArgvSize -= AVsz + 1;\r
103 if(nArgvSize < 0) {\r
104 Print(L"ABORTING: Internal Argv[%d] conversion error.\n", count);\r
105 exit(EXIT_FAILURE);\r
106 /* Not Reached */\r
107 }\r
108 }\r
109 return gMD->NArgV;\r
110}\r
111\r
2aa62f2b 112INTN\r
113EFIAPI\r
114ShellAppMain (\r
115 IN UINTN Argc,\r
116 IN CHAR16 **Argv\r
117 )\r
118{\r
53e1e5c6 119 struct __filedes *mfd;\r
120 char **nArgv;\r
2aa62f2b 121 INTN ExitVal;\r
122 INTN i;\r
2aa62f2b 123\r
124 ExitVal = (INTN)RETURN_SUCCESS;\r
125 gMD = AllocateZeroPool(sizeof(struct __MainData));\r
126 if( gMD == NULL ) {\r
127 ExitVal = (INTN)RETURN_OUT_OF_RESOURCES;\r
128 }\r
129 else {\r
130 /* Initialize data */\r
131 __sse2_available = 0;\r
132 _fltused = 1;\r
133 errno = 0;\r
134 EFIerrno = 0;\r
53e1e5c6 135 gMD->FinalCleanup = &FinalCleanup;\r
2aa62f2b 136\r
137#ifdef NT32dvm\r
53e1e5c6 138 gMD->ClocksPerSecond = 1; // For NT32 only\r
139 gMD->AppStartTime = 1; // For NT32 only\r
2aa62f2b 140#else\r
141 gMD->ClocksPerSecond = (clock_t)GetPerformanceCounterProperties( NULL, NULL);\r
142 gMD->AppStartTime = (clock_t)GetPerformanceCounter();\r
143#endif /* NT32 dvm */\r
144\r
145 // Initialize file descriptors\r
146 mfd = gMD->fdarray;\r
147 for(i = 0; i < (FOPEN_MAX); ++i) {\r
148 mfd[i].MyFD = (UINT16)i;\r
149 }\r
150\r
53e1e5c6 151 i = open("stdin:", O_RDONLY, 0444);\r
152 if(i == 0) {\r
153 i = open("stdout:", O_WRONLY, 0222);\r
154 if(i == 1) {\r
155 i = open("stderr:", O_WRONLY, 0222);\r
2aa62f2b 156 }\r
157 }\r
53e1e5c6 158 if(i != 2) {\r
2aa62f2b 159 Print(L"ERROR Initializing Standard IO: %a.\n %r\n",\r
160 strerror(errno), EFIerrno);\r
161 }\r
162\r
53e1e5c6 163 /* Create mbcs versions of the Argv strings. */\r
164 nArgv = ArgvConvert(Argc, Argv);\r
165 if(nArgv == NULL) {\r
166 ExitVal = (INTN)RETURN_INVALID_PARAMETER;\r
2aa62f2b 167 }\r
53e1e5c6 168 else {\r
169 ExitVal = (INTN)main( (int)Argc, nArgv);\r
2aa62f2b 170 }\r
2aa62f2b 171 }\r
53e1e5c6 172 exit((int)ExitVal);\r
173 /* Not Reached */\r
2aa62f2b 174 return ExitVal;\r
175}\r