Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

558 lines
12 KiB

  1. #include <efi.h>
  2. #include <efilib.h>
  3. //
  4. // Prototype
  5. //
  6. void ParseArgs (EFI_LOADED_IMAGE *ImageHdl);
  7. void Launch (CHAR16 *exePath);
  8. EFI_STATUS OpenCreateFile (UINT64 OCFlags,EFI_FILE_HANDLE *StartHdl,CHAR16 *FileName);
  9. void ParseBootFile (EFI_FILE_HANDLE BootFile);
  10. void PopulateStartFile (EFI_FILE_HANDLE StartFile);
  11. void TrimNonPrint(CHAR16 * str);
  12. CHAR16 * __cdecl mystrstr (const CHAR16 * str1,const CHAR16 * str2);
  13. CHAR16 * ParseLine (CHAR16 *optCopy);
  14. //
  15. //Globals
  16. //
  17. EFI_HANDLE ExeHdl;
  18. EFI_LOADED_IMAGE *ExeImage;
  19. //
  20. // Defines
  21. //
  22. #define REGISTER1 L"*register"
  23. #define REGISTER2 L"*register*"
  24. #define STARTFILE L"startup.nsh"
  25. #define BOOTOFILE L"boot.nvr"
  26. #define OSLOADOPT L"OSLOADER"
  27. #define PARTENT L"partition"
  28. #define PARTENTRE L"*partition*"
  29. EFI_STATUS
  30. EfiMain ( IN EFI_HANDLE ImageHandle,
  31. IN EFI_SYSTEM_TABLE *SystemTable)
  32. {
  33. EFI_STATUS Status;
  34. EFI_FILE_HANDLE bootFile;
  35. InitializeLib (ImageHandle, SystemTable);
  36. ExeHdl = ImageHandle;
  37. BS->HandleProtocol (ImageHandle, &LoadedImageProtocol, &ExeImage);
  38. ParseArgs(ExeImage);
  39. //
  40. // Read the bootfile
  41. //
  42. Status = OpenCreateFile (EFI_FILE_MODE_READ,&bootFile,BOOTOFILE);
  43. ParseBootFile (bootFile);
  44. //
  45. // If we get here, we failed to load the OS
  46. //
  47. return EFI_SUCCESS;
  48. }
  49. void
  50. ParseArgs (EFI_LOADED_IMAGE *ImageInfo)
  51. {
  52. BOOLEAN optFound;
  53. EFI_STATUS Status;
  54. EFI_FILE_HANDLE startFile;
  55. if (MetaiMatch (ImageInfo->LoadOptions,REGISTER1) ||
  56. MetaiMatch (ImageInfo->LoadOptions,REGISTER2)) {
  57. Status = OpenCreateFile (EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE,&startFile,STARTFILE);
  58. if (!(EFI_ERROR (Status))) {
  59. PopulateStartFile (startFile);
  60. BS->Exit (ExeHdl,EFI_SUCCESS,0,NULL);
  61. }
  62. }
  63. }
  64. void
  65. Launch (CHAR16 *exePath)
  66. {
  67. EFI_HANDLE exeHdl=NULL;
  68. UINTN i;
  69. EFI_DEVICE_PATH *ldrDevPath;
  70. EFI_STATUS Status;
  71. EFI_FILE_IO_INTERFACE *Vol;
  72. EFI_FILE_HANDLE RootFs;
  73. EFI_FILE_HANDLE CurDir;
  74. EFI_FILE_HANDLE FileHandle;
  75. CHAR16 FileName[100],*DevicePathAsString;
  76. //
  77. // Open the volume for the device where the exe was loaded from.
  78. //
  79. Status = BS->HandleProtocol (ExeImage->DeviceHandle,
  80. &FileSystemProtocol,
  81. &Vol
  82. );
  83. if (EFI_ERROR(Status)) {
  84. Print(L"Can not get a FileSystem handle for ExeImage->DeviceHandle\n");
  85. BS->Exit(ExeHdl,EFI_SUCCESS,0,NULL);
  86. }
  87. Status = Vol->OpenVolume (Vol, &RootFs);
  88. if (EFI_ERROR(Status)) {
  89. Print(L"Can not open the volume for the file system\n");
  90. BS->Exit(ExeHdl,EFI_SUCCESS,0,NULL);
  91. }
  92. CurDir = RootFs;
  93. //
  94. // Open the file relative to the root.
  95. //
  96. DevicePathAsString = DevicePathToStr(ExeImage->FilePath);
  97. if (DevicePathAsString!=NULL) {
  98. StrCpy(FileName,DevicePathAsString);
  99. FreePool(DevicePathAsString);
  100. }
  101. FileName[0] = 0;
  102. StrCat(FileName,exePath);
  103. // size = StrLen(FileName);
  104. // Print(L"Length of filename is %d\n", size);
  105. // DumpHex(4, 0, 10, &FileName[size - 4]);
  106. //
  107. // Get rid of trailing spaces, new lines, whatever
  108. //
  109. TrimNonPrint(FileName);
  110. Status = CurDir->Open (CurDir,
  111. &FileHandle,
  112. FileName,
  113. EFI_FILE_MODE_READ,
  114. 0
  115. );
  116. if (EFI_ERROR(Status)) {
  117. Print(L"Can not open the file ->%s<-, error was %X\n",FileName, Status);
  118. BS->Exit(ExeHdl,EFI_SUCCESS,0,NULL);
  119. } else {
  120. // Print(L"Opened %s\n",FileName);
  121. }
  122. ldrDevPath = FileDevicePath (ExeImage->DeviceHandle,FileName);
  123. /*
  124. if (ldrDevPath) {
  125. Print (L"Type: %d\nSub-Type: %d\nLength[0][1]: [%d][%d]\n",ldrDevPath->Type,
  126. ldrDevPath->SubType,ldrDevPath->Length[0],ldrDevPath->Length[1]);
  127. }else {
  128. Print (L"bad dev path\n");
  129. }
  130. */
  131. // DumpHex (4,0,ldrDevPath->Length[0],ldrDevPath);
  132. Status = BS->LoadImage (FALSE,ExeHdl,ldrDevPath,NULL,0,&exeHdl);
  133. if (!(EFI_ERROR (Status))) {
  134. // Print (L"Image loaded!\n");
  135. }else {
  136. Print (L"Load Error: %X\n",Status);
  137. BS->Exit(ExeHdl,EFI_SUCCESS,0,NULL);
  138. }
  139. FreePool (ldrDevPath);
  140. BS->StartImage (exeHdl,&i,NULL);
  141. return;
  142. }
  143. EFI_STATUS
  144. OpenCreateFile (UINT64 OCFlags,EFI_FILE_HANDLE *StartHdl,CHAR16 *Name)
  145. {
  146. EFI_FILE_IO_INTERFACE *Vol;
  147. EFI_FILE_HANDLE RootFs;
  148. EFI_FILE_HANDLE CurDir;
  149. EFI_FILE_HANDLE FileHandle;
  150. CHAR16 FileName[100],*DevicePathAsString;
  151. UINTN i;
  152. EFI_STATUS Status;
  153. //
  154. // Open the volume for the device where the EFI OS Loader was loaded from.
  155. //
  156. Status = BS->HandleProtocol (ExeImage->DeviceHandle,
  157. &FileSystemProtocol,
  158. &Vol
  159. );
  160. if (EFI_ERROR(Status)) {
  161. Print(L"Can not get a FileSystem handle for %s DeviceHandle\n",ExeImage->FilePath);
  162. BS->Exit(ExeHdl,EFI_SUCCESS,0,NULL);
  163. }
  164. Status = Vol->OpenVolume (Vol, &RootFs);
  165. if (EFI_ERROR(Status)) {
  166. Print(L"Can not open the volume for the file system\n");
  167. BS->Exit(ExeHdl,EFI_SUCCESS,0,NULL);
  168. }
  169. CurDir = RootFs;
  170. //
  171. // Open the startup options file in the same path as the launcher
  172. //
  173. DevicePathAsString = DevicePathToStr(ExeImage->FilePath);
  174. if (DevicePathAsString!=NULL) {
  175. StrCpy(FileName,DevicePathAsString);
  176. FreePool(DevicePathAsString);
  177. }
  178. for(i=StrLen(FileName);i>0 && FileName[i]!='\\';i--);
  179. FileName[i] = 0;
  180. StrCat(FileName,Name);
  181. Status = CurDir->Open (CurDir,
  182. &FileHandle,
  183. FileName,
  184. OCFlags,
  185. 0
  186. );
  187. if (EFI_ERROR(Status)) {
  188. Print(L"Can not open the file %s\n",FileName);
  189. BS->Exit(ExeHdl,EFI_SUCCESS,0,NULL);
  190. }
  191. *StartHdl=FileHandle;
  192. // Print(L"Opened %s\n",FileName);
  193. return Status;
  194. }
  195. void ParseBootFile (EFI_FILE_HANDLE BootFile)
  196. {
  197. EFI_STATUS Status;
  198. char *buffer,*t;
  199. CHAR16 *uniBuf,*optBegin,*optEnd,*optCopy;
  200. UINTN i,size;
  201. EFI_FILE_INFO *bootInfo;
  202. size= SIZE_OF_EFI_FILE_INFO+255*sizeof (CHAR16);
  203. bootInfo = AllocatePool (size);
  204. if (bootInfo == NULL) {
  205. Print (L"Failed to allocate memory for File Info buffer!\n");
  206. BS->Exit(ExeHdl,EFI_SUCCESS,0,NULL);
  207. }
  208. Status = BootFile->GetInfo(BootFile,&GenericFileInfo,&size,bootInfo);
  209. size=(UINTN) bootInfo->FileSize;
  210. FreePool (bootInfo);
  211. buffer = AllocatePool ((size+1));
  212. if (buffer == NULL) {
  213. Print (L"Failed to allocate memory for File buffer!\n");
  214. BS->Exit(ExeHdl,EFI_SUCCESS,0,NULL);
  215. }
  216. Status = BootFile->Read(BootFile,&size,buffer);
  217. BootFile->Close (BootFile);
  218. if (EFI_ERROR (Status)) {
  219. Print (L"Failed to read bootfile!\n");
  220. FreePool (buffer);
  221. BS->Exit(ExeHdl,EFI_SUCCESS,0,NULL);
  222. }
  223. //
  224. // allocate FileSize's space worth of unicode chars.
  225. // (the file is in ASCII)
  226. //
  227. uniBuf = AllocateZeroPool ((size+1) * sizeof (CHAR16));
  228. if (uniBuf == NULL) {
  229. Print (L"Failed to allocate memory for Unicode buffer!\n");
  230. FreePool (buffer);
  231. BS->Exit(ExeHdl,EFI_SUCCESS,0,NULL);
  232. }
  233. t=(char *)uniBuf;
  234. //
  235. // Convert the buffer to a hacked unicode.
  236. //
  237. for (i=0;i<size;i++) {
  238. *(t+i*2)=*(buffer+i);
  239. }
  240. //
  241. //find the option we care about
  242. //
  243. optBegin = mystrstr (uniBuf,OSLOADOPT);
  244. //
  245. // find the end
  246. //
  247. optEnd = optBegin;
  248. while (*(optEnd++) != '\n');
  249. optCopy = AllocateZeroPool (((optEnd-optBegin)+2)*sizeof (CHAR16));
  250. if (optCopy == NULL) {
  251. Print (L"Failed to allocate memory for Unicode buffer!\n");
  252. FreePool (buffer);
  253. FreePool (uniBuf);
  254. BS->Exit(ExeHdl,EFI_SUCCESS,0,NULL);
  255. }
  256. CopyMem (optCopy,optBegin,(optEnd-optBegin)*sizeof (CHAR16));
  257. // Print (L"copied to unicode:%d bytes\n%lX\n%lX\n%s\n",(optEnd-optBegin)*sizeof(CHAR16),optEnd,optBegin,optCopy);
  258. FreePool (uniBuf);
  259. FreePool (buffer);
  260. //
  261. // re-using uniBuf;
  262. //
  263. uniBuf=optBegin=optCopy;
  264. uniBuf =ParseLine (optCopy);
  265. #if 0
  266. do {
  267. uniBuf = mystrstr (uniBuf,PARTENT);
  268. if (uniBuf) {
  269. uniBuf+= StrLen (PARTENT);
  270. optBegin = uniBuf;
  271. }
  272. } while ( uniBuf );
  273. //
  274. // optBegin points to the last partition(n) value
  275. //
  276. while (*(optBegin++) != ')');
  277. optEnd = ++optBegin;
  278. while ((*optEnd != ';') && (*optEnd != '\n')) {
  279. optEnd++;
  280. }
  281. uniBuf = AllocateZeroPool (((optEnd-optBegin)+1)*sizeof (CHAR16));
  282. CopyMem (uniBuf,optBegin,(optEnd-optBegin)*sizeof (CHAR16));
  283. #endif
  284. Print (L"Will launch... %s\n",uniBuf);
  285. Print (L"\nPress any key to abort autoload\n");
  286. Status = WaitForSingleEvent (ST->ConIn->WaitForKey,5*10000000);
  287. if (Status != EFI_TIMEOUT){
  288. BS->Exit(ExeHdl,EFI_SUCCESS,0,NULL);
  289. }
  290. Launch (uniBuf);
  291. FreePool (optCopy);
  292. }
  293. //
  294. // fill out startup.nsh with the name of this program
  295. //
  296. void PopulateStartFile (EFI_FILE_HANDLE StartFile)
  297. {
  298. CHAR16 *NameBuf;
  299. EFI_STATUS Status;
  300. UINTN i,size;
  301. EFI_FILE_INFO *bootInfo;
  302. CHAR16 UnicodeMarker = UNICODE_BYTE_ORDER_MARK;
  303. size= SIZE_OF_EFI_FILE_INFO+255*sizeof (CHAR16);
  304. bootInfo = AllocatePool (size);
  305. if (bootInfo == NULL) {
  306. Print (L"Failed to allocate memory for File Info buffer!\n");
  307. BS->Exit(ExeHdl,EFI_SUCCESS,0,NULL);
  308. }
  309. size = sizeof(UnicodeMarker);
  310. StartFile->Write(StartFile, &size, &UnicodeMarker);
  311. NameBuf=DevicePathToStr (ExeImage->FilePath);
  312. while (*(++NameBuf) != '\\');
  313. //
  314. // take off 4 for the '.efi' extension, which hangs the shell!!!!!
  315. //
  316. size= (StrLen (NameBuf)+2)*sizeof (CHAR16);
  317. StartFile->Write (StartFile,&size,NameBuf);
  318. size = sizeof (CHAR16);
  319. StartFile->Write (StartFile,&size,&L"\n");
  320. StartFile->Close (StartFile);
  321. FreePool (bootInfo);
  322. }
  323. CHAR16*
  324. ParseLine (CHAR16 *optCopy)
  325. {
  326. EFI_STATUS Status;
  327. UINTN i,len,count=0;
  328. CHAR16 *p;
  329. // Print (L"ParseLine: working on %s\n",optCopy);
  330. len=StrLen (optCopy);
  331. //
  332. // Figure out how many tokens there are in the option line
  333. // it will be: TOKENNAME=a;b;c
  334. // (watch for a;b;c;)
  335. //
  336. for (i=0;i<len-1;i++) {
  337. if (*(optCopy+i) == ';') {
  338. count++;
  339. }
  340. }
  341. while (*(++optCopy) != '=');
  342. //
  343. // strip the arc info
  344. //
  345. while (*(++optCopy) != '\\');
  346. p = ++optCopy;
  347. while (*optCopy != '\0' && *optCopy != ';') {
  348. optCopy++;
  349. }
  350. *optCopy='\0';
  351. return (p);
  352. }
  353. /***
  354. *CHAR16 *mystrstr(string1, string2) - search for string2 in string1
  355. *
  356. *Purpose:
  357. * finds the first occurrence of string2 in string1
  358. *
  359. *Entry:
  360. * CHAR16 *string1 - string to search in
  361. * CHAR16 *string2 - string to search for
  362. *
  363. *Exit:
  364. * returns a pointer to the first occurrence of string2 in
  365. * string1, or NULL if string2 does not occur in string1
  366. *
  367. *Uses:
  368. *
  369. *Exceptions:
  370. *
  371. *******************************************************************************/
  372. CHAR16 * __cdecl mystrstr (
  373. const CHAR16 * str1,
  374. const CHAR16 * str2
  375. )
  376. {
  377. CHAR16 *cp = (CHAR16 *) str1;
  378. CHAR16 *s1, *s2;
  379. if ( !*str2 )
  380. return((CHAR16 *)str1);
  381. while (*cp)
  382. {
  383. s1 = cp;
  384. s2 = (CHAR16 *) str2;
  385. while ( *s1 && *s2 && !(*s1-*s2) )
  386. s1++, s2++;
  387. if (!*s2)
  388. return(cp);
  389. cp++;
  390. }
  391. return(NULL);
  392. }
  393. void
  394. TrimNonPrint(
  395. CHAR16 * str
  396. )
  397. {
  398. INTN i,size;
  399. if ((NULL == str) || (L'\0' == *str)) {
  400. return;
  401. }
  402. size = (INTN) StrLen(str);
  403. // Print(L"Size is %d\n", size);
  404. // DumpHex(4, 0, 2, &str[size]);
  405. for (i = size; i > 0; i--) {
  406. if (str[i] <= 0x20) {
  407. str[i] = L'\0';
  408. }
  409. else {
  410. // Leave when we hit a legit character
  411. break;
  412. }
  413. }
  414. }