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.

597 lines
18 KiB

  1. /*++
  2. Copyright (c) 1999-2001 Microsoft Corporation
  3. Module Name:
  4. efifmt.cxx
  5. Abstract:
  6. This is the main program for the efi version of format.
  7. --*/
  8. #pragma warning(disable: 4091)
  9. #include "ulib.hxx"
  10. #include "wstring.hxx"
  11. #include "efickmsg.hxx"
  12. #include "error.hxx"
  13. #include "ifssys.hxx"
  14. #include "rtmsg.h"
  15. #include "ifsentry.hxx"
  16. #include "fatvol.hxx"
  17. #include "layout.hxx"
  18. #include "efiwintypes.hxx"
  19. extern "C" BOOLEAN
  20. InitializeUfat(
  21. PVOID DllHandle,
  22. ULONG Reason,
  23. PCONTEXT Context
  24. );
  25. extern "C"
  26. BOOLEAN
  27. InitializeIfsUtil(
  28. PVOID DllHandle,
  29. ULONG Reason,
  30. PCONTEXT Context
  31. );
  32. int __cdecl
  33. main(
  34. int argc,
  35. WCHAR** argv,
  36. WCHAR** envp
  37. );
  38. int argc;
  39. WCHAR ** argv;
  40. #if defined(EFI_DEBUG)
  41. VOID
  42. PrintLoadedImageInfo (
  43. IN EFI_LOADED_IMAGE *LoadedImage
  44. );
  45. #endif
  46. VOID
  47. InvokeAutoFmtMain (
  48. IN EFI_HANDLE ImageHandle,
  49. IN EFI_LOADED_IMAGE *LoadedImage
  50. );
  51. extern "C" {
  52. EFI_STATUS
  53. __declspec(dllexport)
  54. InitializeEfiFmtApplication(
  55. IN EFI_HANDLE ImageHandle,
  56. IN EFI_SYSTEM_TABLE *SystemTable
  57. )
  58. {
  59. EFI_LOADED_IMAGE *LoadedImage;
  60. /*
  61. * Initialize the Library. Set BS, RT, &ST globals
  62. * BS = Boot Services RT = RunTime Services
  63. * ST = System Table
  64. */
  65. InitializeLib (ImageHandle, SystemTable);
  66. InitializeShellApplication( ImageHandle, SystemTable );
  67. DEBUG((D_INFO,(CHAR8*)"EFIFMT application started\n"));
  68. Print(TEXT("EFI Disk Format Version 0.2\n"));
  69. Print(TEXT("Based on EFI Core "));
  70. Print(TEXT("Version %d.%d.%d.%d\n"),
  71. EFI_SPECIFICATION_MAJOR_REVISION,
  72. EFI_SPECIFICATION_MINOR_REVISION,
  73. EFI_FIRMWARE_MAJOR_REVISION,
  74. EFI_FIRMWARE_MINOR_REVISION
  75. );
  76. BS->HandleProtocol (ImageHandle, &LoadedImageProtocol, (VOID**)&LoadedImage);
  77. #if 0
  78. PrintLoadedImageInfo (LoadedImage);
  79. #endif
  80. // call into autofmt.
  81. InvokeAutoFmtMain (ImageHandle, LoadedImage);
  82. #if 0
  83. EfiWaitForKey();
  84. ST->ConOut->OutputString (ST->ConOut, TEXT("\n\n"));
  85. #endif
  86. return EFI_SUCCESS;
  87. }
  88. } // extern "C"
  89. UINT16 *MemoryType[] = {
  90. TEXT("reserved "),
  91. TEXT("LoaderCode"),
  92. TEXT("LoaderData"),
  93. TEXT("BS_code "),
  94. TEXT("BS_data "),
  95. TEXT("RT_code "),
  96. TEXT("RT_data "),
  97. TEXT("available "),
  98. TEXT("Unusable "),
  99. TEXT("ACPI_recl "),
  100. TEXT("ACPI_NVS "),
  101. TEXT("MemMapIO "),
  102. TEXT("MemPortIO "),
  103. TEXT("PAL_code "),
  104. TEXT("BUG:BUG: MaxMemoryType")
  105. };
  106. VOID
  107. InvokeAutoFmtMain (
  108. IN EFI_HANDLE ImageHandle,
  109. IN EFI_LOADED_IMAGE *LoadedImage
  110. )
  111. {
  112. EFI_LOADED_IMAGE *ParentImage;
  113. if (!LoadedImage->ParentHandle) {
  114. /*
  115. * If you are loaded from the EFI boot manager the ParentHandle
  116. * is Null. Thus a pure EFI application will not have a parrent.
  117. */
  118. DEBUG((D_INFO,(CHAR8*)"\n%HImage was loaded from EFI Boot Manager%N\n"));
  119. return;
  120. }
  121. BS->HandleProtocol (LoadedImage->ParentHandle, &LoadedImageProtocol, (VOID**)&ParentImage);
  122. #if 0
  123. Print(TEXT("\n%HImage Parent was %N%s %Hand it passed the following arguments:%N \n %s\n\n"), DevicePathToStr (ParentImage->FilePath),LoadedImage->LoadOptions);
  124. #endif
  125. {
  126. argc = SI->Argc;
  127. argv = SI->Argv;
  128. DEBUG((D_INFO,(CHAR8*)"Launching main...\n"));
  129. // call main.
  130. main(argc,argv,NULL);
  131. DEBUG((D_INFO,(CHAR8*)"Returned from main...\n"));
  132. }
  133. }
  134. #if defined(EFI_DEBUG)
  135. VOID
  136. PrintLoadedImageInfo (
  137. IN EFI_LOADED_IMAGE *LoadedImage
  138. )
  139. {
  140. EFI_STATUS Status;
  141. EFI_DEVICE_PATH *DevicePath;
  142. Print(TEXT("\n%HImage was loaded from file %N%s\n"), DevicePathToStr (LoadedImage->FilePath));
  143. BS->HandleProtocol (LoadedImage->DeviceHandle, &DevicePathProtocol, (VOID**)&DevicePath);
  144. if (DevicePath) {
  145. Print(TEXT("%HImage was loaded from this device %N%s\n"), DevicePathToStr (DevicePath));
  146. }
  147. Print(TEXT("\n Image Base is %X"), LoadedImage->ImageBase);
  148. Print(TEXT("\n Image Size is %X"), LoadedImage->ImageSize);
  149. Print(TEXT("\n Image Code Type %s"), MemoryType[LoadedImage->ImageCodeType]);
  150. Print(TEXT("\n Image Data Type %s"), MemoryType[LoadedImage->ImageDataType]);
  151. Print(TEXT("\n %d Bytes of Options passed to this Image\n"), LoadedImage->LoadOptionsSize);
  152. if (LoadedImage->ParentHandle) {
  153. Status = BS->HandleProtocol (LoadedImage->ParentHandle, &DevicePathProtocol, (VOID**)&DevicePath);
  154. if (Status == EFI_SUCCESS && DevicePath) {
  155. Print(TEXT("Images parent is %s\n\n"), DevicePathToStr (DevicePath));
  156. }
  157. }
  158. }
  159. #endif
  160. int __cdecl
  161. main(
  162. int argc,
  163. WCHAR** argv,
  164. WCHAR** envp
  165. )
  166. /*++
  167. Routine Description:
  168. This routine is the main program for AutoFmt
  169. Arguments:
  170. argc, argv - Supplies the fully qualified NT path name of the
  171. the drive to check. The syntax of the autofmt
  172. command line is:
  173. AUTOFMT drive-name /FS:target-file-system [/V:label] [/Q] [/A:size] [/C]
  174. [/S]
  175. Return Value:
  176. 0 - Success.
  177. 1 - Failure.
  178. --*/
  179. {
  180. if (!InitializeUlib( NULL, ! DLL_PROCESS_DETACH, NULL ) ||
  181. !InitializeIfsUtil(NULL, ! DLL_PROCESS_DETACH, NULL) ||
  182. !InitializeUfat(NULL, ! DLL_PROCESS_DETACH, NULL)
  183. ) {
  184. return 1;
  185. }
  186. PFAT_VOL fat_volume;
  187. PDP_DRIVE dp_drive;
  188. EFICHECK_MESSAGE *message = NULL;
  189. DSTRING drive_name;
  190. DSTRING file_system_name;
  191. DSTRING label;
  192. DSTRING* plabel;
  193. DSTRING fat_name;
  194. DSTRING fat32_name;
  195. DSTRING raw_name;
  196. BOOLEAN quick = FALSE;
  197. BOOLEAN compress = FALSE;
  198. FORMAT_ERROR_CODE success;
  199. BOOLEAN setup_output = FALSE;
  200. BOOLEAN textmode_output = FALSE;
  201. BOOLEAN drive_already_specified = FALSE;
  202. BOOLEAN force_filesystem = FALSE;
  203. BOOLEAN showhelp = FALSE;
  204. BOOLEAN labelled = FALSE;
  205. BIG_INT bigint;
  206. ULONG cluster_size = 0;
  207. int i;
  208. NTSTATUS result;
  209. if (!(perrstk = NEW ERRSTACK)) {
  210. return 1;
  211. }
  212. if (!file_system_name.Initialize()) {
  213. return 1;
  214. }
  215. if (!label.Initialize() || NULL == (dp_drive = NEW DP_DRIVE)) {
  216. return 1;
  217. }
  218. //
  219. // Parse the arguments.
  220. //
  221. // if ( argc < 2 ) {
  222. // return 1;
  223. // }
  224. message = NEW EFICHECK_MESSAGE;
  225. if (NULL == message || !message->Initialize()) {
  226. return 1;
  227. }
  228. //
  229. // The rest of the arguments are flags.
  230. //
  231. for (i = 1; i < argc; i++) {
  232. if (((argv[i][0] == '/' || argv[i][0] == '=') &&
  233. (argv[i][1] == '?' )) || showhelp
  234. ) {
  235. showhelp = TRUE;
  236. }
  237. else if ((argv[i][0] == '/' || argv[i][0] == '-') &&
  238. (argv[i][1] == 'f' || argv[i][1] == 'F') &&
  239. (argv[i][2] == 's' || argv[i][2] == 'S') &&
  240. (argv[i][3] == ':')) {
  241. if (!file_system_name.Initialize(&argv[i][4])) {
  242. return 1;
  243. }
  244. force_filesystem = TRUE;
  245. DEBUG((D_INFO,(CHAR8*)"fsname: %ws\n", file_system_name.GetWSTR()));
  246. }
  247. else if ((argv[i][0] == '/' || argv[i][0] == '-') &&
  248. (argv[i][1] == 'v' || argv[i][1] == 'V') &&
  249. (argv[i][2] == ':')) {
  250. if (!label.Initialize(&argv[i][3])) {
  251. return 1;
  252. }
  253. labelled = TRUE;
  254. }
  255. else if ((argv[i][0] == '/' || argv[i][0] == '-') &&
  256. (argv[i][1] == 'a' || argv[i][1] == 'A') &&
  257. (argv[i][2] == ':')) {
  258. // Check to see if the size is specified in Kb
  259. if ((argv[i][StrLen(argv[i])-1] == 'k') || (argv[i][StrLen(argv[i])-1] == 'K')) {
  260. argv[i][StrLen(argv[i])-1] = '\0'; // remove the K and null terminate the string
  261. cluster_size = (ULONG)Atoi(&argv[i][3]) * 1024;
  262. }
  263. else {
  264. cluster_size = (ULONG)Atoi(&argv[i][3]);
  265. }
  266. }
  267. else if (0 == StriCmp(argv[i], TEXT("/Q")) || 0 == StriCmp(argv[i], TEXT("-Q"))) {
  268. quick = TRUE;
  269. }
  270. else if (argv[i][0] != '/' && argv[i][0] != '-') {
  271. // it's not a switch, assume it is the drive
  272. // we don't allow two drive at the same time
  273. if( drive_already_specified ) {
  274. message->Set(MSG_FMT_INVALID_DRIVE_SPEC);
  275. message->Display();
  276. return 1;
  277. }
  278. drive_already_specified = TRUE;
  279. if ( !drive_name.Initialize( argv[i] ) ) {
  280. return 1;
  281. }
  282. DEBUG((D_INFO,(CHAR8*)"drive name: %ws\n", drive_name.GetWSTR()));
  283. }
  284. else {
  285. // its not any vaild option we know of
  286. message->Set(MSG_INVALID_PARAMETER);
  287. message->Display("%ws",argv[i]);
  288. message->Set(MSG_BLANK_LINE);
  289. message->Display();
  290. showhelp = TRUE;
  291. }
  292. }
  293. DEBUG((D_INFO,(CHAR8*)"Parsed Args.\n"));
  294. if(showhelp || !drive_already_specified) {
  295. message->Set(MSG_FORMAT_INFO);
  296. message->Display();
  297. message->Set(MSG_FORMAT_COMMAND_LINE_1);
  298. message->Display();
  299. message->Set(MSG_FORMAT_COMMAND_LINE_2);
  300. message->Display();
  301. message->Set(MSG_FORMAT_COMMAND_LINE_4);
  302. message->Display();
  303. message->Set(MSG_FORMAT_SLASH_V);
  304. message->Display();
  305. message->Set(MSG_FORMAT_SLASH_Q);
  306. message->Display();
  307. message->Set(MSG_FORMAT_SLASH_F);
  308. message->Display();
  309. message->Set(MSG_FORMAT_SUPPORTED_SIZES);
  310. message->Display();
  311. return 1;
  312. }
  313. textmode_output = TRUE;
  314. #if 0 // Shouldn't limit the cluster size as long as it is reasonable.
  315. if (cluster_size != 0 && cluster_size != 512 && cluster_size != 1024 &&
  316. cluster_size != 2048 && cluster_size != 4096) {
  317. message->Set(MSG_UNSUPPORTED_PARAMETER);
  318. message->Display();
  319. DeRegister( argc, argv );
  320. return 1;
  321. }
  322. #endif
  323. DEBUG((D_INFO,(CHAR8*)"Determining file system type.\n"));
  324. if (0 == file_system_name.QueryChCount()) {
  325. // attempt to get the current filesystem type from disk
  326. if (!IFS_SYSTEM::QueryFileSystemName(&drive_name, &file_system_name, &result, NULL)) {
  327. message->Set( MSG_FS_NOT_DETERMINED );
  328. message->Display( "%W", &drive_name );
  329. DEBUG((D_ERROR,(CHAR8*)"Unable to determine file system type.\n"));
  330. if(result != 0) {
  331. message->Set(MSG_CANT_DASD);
  332. message->Display();
  333. }
  334. return 1;
  335. }
  336. file_system_name.Strupr();
  337. }
  338. if (!fat_name.Initialize("FAT") ||
  339. !fat32_name.Initialize("FAT32") ||
  340. !raw_name.Initialize("RAW") ) {
  341. return 1;
  342. }
  343. file_system_name.Strupr();
  344. //
  345. // If compression is requested, make sure it's available.
  346. //
  347. #if 0
  348. if (compress) {
  349. message->Set(MSG_COMPRESSION_NOT_AVAILABLE);
  350. message->Display("%W", &file_system_name);
  351. return 1;
  352. }
  353. #endif
  354. DEBUG((D_INFO,(CHAR8*)"Init DP_DRIVE.\n"));
  355. if (!dp_drive->Initialize(&drive_name, message)) {
  356. DEBUG((D_ERROR,(CHAR8*)"Failed Init DP_DRIVE.\n"));
  357. return 1;
  358. }
  359. DEBUG((D_INFO,(CHAR8*)"Init DP_DRIVE success.\n"));
  360. message->Set(MSG_WARNING_FORMAT);
  361. message->Display("%W", &drive_name);
  362. if (!message->IsYesResponse(FALSE)) {
  363. return 5;
  364. }
  365. if (dp_drive->IsFloppy()) {
  366. DEBUG((D_INFO,(CHAR8*)"**** Is a floppy.\n"));
  367. // return 1; BUGBUG should i fail this?
  368. }
  369. //
  370. // Print the "formatting <size>" message.
  371. //
  372. if (quick) {
  373. message->Set(MSG_QUICKFORMATTING_MB);
  374. } else {
  375. message->Set(MSG_FORMATTING_MB);
  376. }
  377. if( labelled == FALSE ) {
  378. plabel = NULL;
  379. } else {
  380. plabel = &label;
  381. }
  382. DEBUG((D_INFO,(CHAR8*)"QuerySector count.\n"));
  383. bigint = dp_drive->QuerySectors() * dp_drive->QuerySectorSize() /
  384. 1048576;
  385. DEBUG((D_INFO,(CHAR8*)"Sector count is %ld.\n",dp_drive->QuerySectors()));
  386. DEBUG((D_INFO,(CHAR8*)"Sector size is %d.\n",dp_drive->QuerySectorSize()));
  387. DebugAssert(bigint.GetHighPart() == 0);
  388. message->Display("%d", bigint.GetLowPart());
  389. #if 0
  390. PART_DESCRIPTOR partdes;
  391. UINT32 fatsize;
  392. // if the user hasn't forced a filesystem
  393. if( force_filesystem == FALSE ) {
  394. // if the disk is big enough to put at least FAT16 on it
  395. if (dp_drive->QuerySectors() >= (ULONG)MinSectorsFat16(dp_drive->QuerySectorSize())) {
  396. DEBUG((D_INFO,(CHAR8*)"Drive is big enough for FAT16 >= %d.\n",MinSectorsFat16(dp_drive->QuerySectorSize())));
  397. partdes.SectorCount = (dp_drive->QuerySectors()).GetQuadPart();
  398. partdes.SectorSize = dp_drive->QuerySectorSize();
  399. partdes.HeaderCount = HEADER_F16;
  400. partdes.FatEntrySize = 2;
  401. partdes.MinClusterCount = MIN_CLUSTER_F16;
  402. partdes.MaxClusterCount = MAX_CLUSTER_F16;
  403. partdes.FatType = FAT_TYPE_F16;
  404. file_system_name.Initialize(fat_name.QueryWSTR());
  405. // if this disk is big enough for FAT32
  406. if (dp_drive->QuerySectors() >= (ULONG)MinSectorsFat32(dp_drive->QuerySectorSize())) {
  407. DEBUG((D_INFO,(CHAR8*)"Drive is big enough for FAT32 >= %d\n",MinSectorsFat32(dp_drive->QuerySectorSize())));
  408. partdes.SectorCount = (dp_drive->QuerySectors()).GetQuadPart();
  409. partdes.SectorSize = dp_drive->QuerySectorSize();
  410. partdes.HeaderCount = HEADER_F32;
  411. partdes.FatEntrySize = 4;
  412. partdes.MinClusterCount = MIN_CLUSTER_F32;
  413. partdes.MaxClusterCount = MAX_CLUSTER_F32;
  414. partdes.FatType = FAT_TYPE_F32;
  415. file_system_name.Initialize(fat32_name.QueryWSTR());
  416. }
  417. // if the user hasn't forced a cluster size, select an appropriate one for him
  418. if( cluster_size==0 ) {
  419. PickClusterSize(&partdes,(UINT32*)&cluster_size,&fatsize); // note this routine doesn't work for FAT12
  420. cluster_size = cluster_size * dp_drive->QuerySectorSize(); // PickClusterSize return cluster size in sectors
  421. DEBUG((D_INFO,(CHAR8*)"User hasn't forced a cluster size, picking %d\n",cluster_size));
  422. }
  423. } else {
  424. // do the default, which is going to be FAT12 and whatever regular format picks.
  425. file_system_name.Initialize(fat_name.QueryWSTR());
  426. }
  427. } else {
  428. // if the drive is big enough for FAT16
  429. if (dp_drive->QuerySectors() >= (ULONG)MinSectorsFat16(dp_drive->QuerySectorSize())) {
  430. // the user forced a file system, did he force a cluster size?
  431. if( cluster_size==0 ) {
  432. // nope, setup and pick a good size
  433. partdes.SectorCount = (dp_drive->QuerySectors()).GetQuadPart();
  434. partdes.SectorSize = dp_drive->QuerySectorSize();
  435. if(file_system_name == fat_name) {
  436. partdes.HeaderCount = HEADER_F16;
  437. partdes.FatEntrySize = 2;
  438. partdes.MinClusterCount = MIN_CLUSTER_F16;
  439. partdes.MaxClusterCount = MAX_CLUSTER_F16;
  440. partdes.FatType = FAT_TYPE_F16;
  441. } else if(file_system_name == fat32_name){
  442. partdes.HeaderCount = HEADER_F32;
  443. partdes.FatEntrySize = 4;
  444. partdes.MinClusterCount = MIN_CLUSTER_F32;
  445. partdes.MaxClusterCount = MAX_CLUSTER_F32;
  446. partdes.FatType = FAT_TYPE_F32;
  447. }
  448. PickClusterSize(&partdes,(UINT32*)&cluster_size,&fatsize); // note this routine doesn't work for FAT12
  449. cluster_size = cluster_size * dp_drive->QuerySectorSize(); // PickClusterSize return cluster size in sectors
  450. DEBUG((D_INFO,(CHAR8*)"FS type forced, user hasn't forced a cluster size, picking %d\n",cluster_size));
  451. }
  452. }
  453. }
  454. #endif
  455. if (file_system_name == fat_name || file_system_name == fat32_name) {
  456. BOOLEAN old_fat_vol = TRUE;
  457. DEBUG((D_INFO,(CHAR8*)"This is an old FAT volume.\n"));
  458. if( file_system_name == fat32_name ) {
  459. old_fat_vol = FALSE;
  460. }
  461. if( !(fat_volume = NEW FAT_VOL) ||
  462. NoError != fat_volume->Initialize( &drive_name, message, FALSE, !quick,
  463. Unknown )) {
  464. DEBUG((D_ERROR,(CHAR8*)"fat_volume init failed.\n"));
  465. //return 1;
  466. }
  467. DEBUG((D_INFO,(CHAR8*)"fat_volume init succeeded.\n"));
  468. success = fat_volume->Format(plabel,
  469. message,
  470. old_fat_vol ? FORMAT_BACKWARD_COMPATIBLE : 0,
  471. cluster_size);
  472. DEBUG((D_INFO,(CHAR8*)"Format return code: %d\n", success));
  473. DELETE( fat_volume );
  474. } else {
  475. DEBUG((D_ERROR,(CHAR8*)"fs not supported.\n"));
  476. message->Set( MSG_FS_NOT_SUPPORTED );
  477. message->Display( "%s%W", "EFIFMT", &file_system_name);
  478. return 1;
  479. }
  480. return (success != NoError);
  481. }