UefiShellBcfgCommandLib.c 69 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900
  1. /** @file
  2. Main file for BCFG command.
  3. (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR>
  4. Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include <Uefi.h>
  8. #include <Guid/GlobalVariable.h>
  9. #include <Guid/ShellLibHiiGuid.h>
  10. #include <Protocol/Shell.h>
  11. #include <Protocol/ShellParameters.h>
  12. #include <Protocol/DevicePath.h>
  13. #include <Protocol/LoadedImage.h>
  14. #include <Protocol/UnicodeCollation.h>
  15. #include <Library/BaseLib.h>
  16. #include <Library/BaseMemoryLib.h>
  17. #include <Library/DebugLib.h>
  18. #include <Library/MemoryAllocationLib.h>
  19. #include <Library/PcdLib.h>
  20. #include <Library/ShellCommandLib.h>
  21. #include <Library/ShellLib.h>
  22. #include <Library/SortLib.h>
  23. #include <Library/UefiLib.h>
  24. #include <Library/UefiRuntimeServicesTableLib.h>
  25. #include <Library/UefiBootServicesTableLib.h>
  26. #include <Library/HiiLib.h>
  27. #include <Library/FileHandleLib.h>
  28. #include <Library/PrintLib.h>
  29. #include <Library/HandleParsingLib.h>
  30. #include <Library/DevicePathLib.h>
  31. #include <Library/UefiBootManagerLib.h>
  32. STATIC CONST CHAR16 mFileName[] = L"ShellCommands";
  33. STATIC EFI_HII_HANDLE gShellBcfgHiiHandle = NULL;
  34. typedef enum {
  35. BcfgTargetBootOrder = 0,
  36. BcfgTargetDriverOrder = 1,
  37. BcfgTargetMax = 2
  38. } BCFG_OPERATION_TARGET;
  39. typedef enum {
  40. BcfgTypeDump = 0,
  41. BcfgTypeAdd = 1,
  42. BcfgTypeAddp = 2,
  43. BcfgTypeAddh = 3,
  44. BcfgTypeRm = 4,
  45. BcfgTypeMv = 5,
  46. BcfgTypeOpt = 6,
  47. BcfgTypeMod = 7,
  48. BcfgTypeModf = 8,
  49. BcfgTypeModp = 9,
  50. BcfgTypeModh = 10,
  51. BcfgTypeMax = 11
  52. } BCFG_OPERATION_TYPE;
  53. typedef struct {
  54. BCFG_OPERATION_TARGET Target;
  55. BCFG_OPERATION_TYPE Type;
  56. UINT16 Number1;
  57. UINT16 Number2;
  58. UINTN HandleIndex;
  59. CHAR16 *FileName;
  60. CHAR16 *Description;
  61. UINT16 *Order;
  62. CONST CHAR16 *OptData;
  63. } BGFG_OPERATION;
  64. /**
  65. Update the optional data for a boot or driver option.
  66. If optional data exists it will be changed.
  67. @param[in] Index The boot or driver option index update.
  68. @param[in] DataSize The size in bytes of Data.
  69. @param[in] Data The buffer for the optioanl data.
  70. @param[in] Target The target of the operation.
  71. @retval EFI_SUCCESS The data was sucessfully updated.
  72. @retval other A error occurred.
  73. **/
  74. EFI_STATUS
  75. UpdateOptionalData(
  76. UINT16 Index,
  77. UINTN DataSize,
  78. UINT8 *Data,
  79. IN CONST BCFG_OPERATION_TARGET Target
  80. )
  81. {
  82. EFI_STATUS Status;
  83. CHAR16 VariableName[12];
  84. UINTN OriginalSize;
  85. UINT8 *OriginalData;
  86. UINTN NewSize;
  87. UINT8 *NewData;
  88. UINTN OriginalOptionDataSize;
  89. UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", Index);
  90. OriginalSize = 0;
  91. OriginalData = NULL;
  92. NewData = NULL;
  93. NewSize = 0;
  94. Status = gRT->GetVariable(
  95. VariableName,
  96. (EFI_GUID*)&gEfiGlobalVariableGuid,
  97. NULL,
  98. &OriginalSize,
  99. OriginalData);
  100. if (Status == EFI_BUFFER_TOO_SMALL) {
  101. OriginalData = AllocateZeroPool(OriginalSize);
  102. if (OriginalData == NULL) {
  103. return (EFI_OUT_OF_RESOURCES);
  104. }
  105. Status = gRT->GetVariable(
  106. VariableName,
  107. (EFI_GUID*)&gEfiGlobalVariableGuid,
  108. NULL,
  109. &OriginalSize,
  110. OriginalData);
  111. }
  112. if (!EFI_ERROR(Status)) {
  113. //
  114. // Allocate new struct and discard old optional data.
  115. //
  116. ASSERT (OriginalData != NULL);
  117. OriginalOptionDataSize = sizeof(UINT32) + sizeof(UINT16) + StrSize(((CHAR16*)(OriginalData + sizeof(UINT32) + sizeof(UINT16))));
  118. OriginalOptionDataSize += (*(UINT16*)(OriginalData + sizeof(UINT32)));
  119. OriginalOptionDataSize -= OriginalSize;
  120. NewSize = OriginalSize - OriginalOptionDataSize + DataSize;
  121. NewData = AllocatePool(NewSize);
  122. if (NewData == NULL) {
  123. Status = EFI_OUT_OF_RESOURCES;
  124. } else {
  125. CopyMem (NewData, OriginalData, OriginalSize - OriginalOptionDataSize);
  126. CopyMem(NewData + OriginalSize - OriginalOptionDataSize, Data, DataSize);
  127. }
  128. }
  129. if (!EFI_ERROR(Status)) {
  130. //
  131. // put the data back under the variable
  132. //
  133. Status = gRT->SetVariable(
  134. VariableName,
  135. (EFI_GUID*)&gEfiGlobalVariableGuid,
  136. EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
  137. NewSize,
  138. NewData);
  139. }
  140. SHELL_FREE_NON_NULL(OriginalData);
  141. SHELL_FREE_NON_NULL(NewData);
  142. return (Status);
  143. }
  144. /**
  145. This function will get a CRC for a boot option.
  146. @param[in, out] Crc The CRC value to return.
  147. @param[in] BootIndex The boot option index to CRC.
  148. @retval EFI_SUCCESS The CRC was sucessfully returned.
  149. @retval other A error occurred.
  150. **/
  151. EFI_STATUS
  152. GetBootOptionCrc(
  153. UINT32 *Crc,
  154. UINT16 BootIndex
  155. )
  156. {
  157. CHAR16 VariableName[12];
  158. EFI_STATUS Status;
  159. UINT8 *Buffer;
  160. UINTN BufferSize;
  161. Buffer = NULL;
  162. BufferSize = 0;
  163. //
  164. // Get the data Buffer
  165. //
  166. UnicodeSPrint(VariableName, sizeof(VariableName), L"%Boot%04x", BootIndex);
  167. Status = gRT->GetVariable(
  168. VariableName,
  169. (EFI_GUID*)&gEfiGlobalVariableGuid,
  170. NULL,
  171. &BufferSize,
  172. NULL);
  173. if (Status == EFI_BUFFER_TOO_SMALL) {
  174. Buffer = AllocateZeroPool(BufferSize);
  175. Status = gRT->GetVariable(
  176. VariableName,
  177. (EFI_GUID*)&gEfiGlobalVariableGuid,
  178. NULL,
  179. &BufferSize,
  180. Buffer);
  181. }
  182. //
  183. // Get the CRC computed
  184. //
  185. if (!EFI_ERROR(Status)) {
  186. Status = gBS->CalculateCrc32 (Buffer, BufferSize, Crc);
  187. }
  188. SHELL_FREE_NON_NULL(Buffer);
  189. return EFI_SUCCESS;
  190. }
  191. /**
  192. This function will populate the device path protocol parameter based on TheHandle.
  193. @param[in] TheHandle Driver handle.
  194. @param[in, out] FilePath On a sucessful return the device path to the handle.
  195. @retval EFI_SUCCESS The device path was sucessfully returned.
  196. @retval other A error from gBS->HandleProtocol.
  197. @sa HandleProtocol
  198. **/
  199. EFI_STATUS
  200. GetDevicePathForDriverHandle (
  201. IN EFI_HANDLE TheHandle,
  202. IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath
  203. )
  204. {
  205. EFI_STATUS Status;
  206. EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
  207. EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
  208. Status = gBS->OpenProtocol (
  209. TheHandle,
  210. &gEfiLoadedImageProtocolGuid,
  211. (VOID**)&LoadedImage,
  212. gImageHandle,
  213. NULL,
  214. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  215. );
  216. if (!EFI_ERROR (Status)) {
  217. Status = gBS->OpenProtocol (
  218. LoadedImage->DeviceHandle,
  219. &gEfiDevicePathProtocolGuid,
  220. (VOID**)&ImageDevicePath,
  221. gImageHandle,
  222. NULL,
  223. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  224. );
  225. if (!EFI_ERROR (Status)) {
  226. // *DevPath = DuplicateDevicePath (ImageDevicePath);
  227. // *FilePath = DuplicateDevicePath (LoadedImage->FilePath);
  228. *FilePath = AppendDevicePath(ImageDevicePath,LoadedImage->FilePath);
  229. gBS->CloseProtocol(
  230. LoadedImage->DeviceHandle,
  231. &gEfiDevicePathProtocolGuid,
  232. gImageHandle,
  233. NULL);
  234. }
  235. gBS->CloseProtocol(
  236. TheHandle,
  237. &gEfiLoadedImageProtocolGuid,
  238. gImageHandle,
  239. NULL);
  240. }
  241. return (Status);
  242. }
  243. /**
  244. Functino to get Device Path by a handle.
  245. @param[in] TheHandle Use it to get DevicePath.
  246. @param[in] Target Boot option target.
  247. @param[in, out] DevicePath On a sucessful return the device path to the handle.
  248. @retval SHELL_INVALID_PARAMETER The handle was NULL.
  249. @retval SHELL_NOT_FOUND Not found device path by handle.
  250. @retval SHELL_SUCCESS Get device path successfully.
  251. **/
  252. SHELL_STATUS
  253. GetDevicePathByHandle(
  254. IN EFI_HANDLE TheHandle,
  255. IN BCFG_OPERATION_TARGET Target,
  256. IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
  257. )
  258. {
  259. EFI_STATUS Status;
  260. SHELL_STATUS ShellStatus;
  261. UINTN DriverBindingHandleCount;
  262. UINTN ParentControllerHandleCount;
  263. UINTN ChildControllerHandleCount;
  264. ShellStatus = SHELL_SUCCESS;
  265. if (TheHandle == NULL) {
  266. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number");
  267. return SHELL_INVALID_PARAMETER;
  268. }
  269. Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (TheHandle, &DriverBindingHandleCount, NULL);
  270. if (EFI_ERROR(Status)) {
  271. DriverBindingHandleCount = 0;
  272. }
  273. Status = PARSE_HANDLE_DATABASE_PARENTS (TheHandle, &ParentControllerHandleCount, NULL);
  274. if (EFI_ERROR (Status)) {
  275. ParentControllerHandleCount = 0;
  276. }
  277. Status = ParseHandleDatabaseForChildControllers (TheHandle, &ChildControllerHandleCount, NULL);
  278. if (EFI_ERROR (Status)) {
  279. ChildControllerHandleCount = 0;
  280. }
  281. Status = gBS->HandleProtocol (TheHandle, &gEfiDevicePathProtocolGuid, (VOID**)DevicePath);
  282. if ( DriverBindingHandleCount > 0 ||
  283. ParentControllerHandleCount > 0 ||
  284. ChildControllerHandleCount > 0 ||
  285. !EFI_ERROR(Status)
  286. ) {
  287. //
  288. // The handle points to a real controller which has a device path.
  289. //
  290. if (Target == BcfgTargetDriverOrder) {
  291. ShellPrintHiiEx (
  292. -1,
  293. -1,
  294. NULL,STRING_TOKEN (STR_GEN_PARAM_INV),
  295. gShellBcfgHiiHandle,
  296. L"bcfg",
  297. L"Handle should point to driver image."
  298. );
  299. ShellStatus = SHELL_NOT_FOUND;
  300. }
  301. } else {
  302. //
  303. // The handle points to a driver image.
  304. //
  305. if (Target == BcfgTargetBootOrder) {
  306. ShellPrintHiiEx (
  307. -1,
  308. -1,
  309. NULL,
  310. STRING_TOKEN (STR_GEN_PARAM_INV),
  311. gShellBcfgHiiHandle,
  312. L"bcfg",
  313. L"Handle should point to controller."
  314. );
  315. ShellStatus = SHELL_NOT_FOUND;
  316. } else {
  317. if (EFI_ERROR (GetDevicePathForDriverHandle (TheHandle, DevicePath))) {
  318. ShellStatus = SHELL_NOT_FOUND;
  319. }
  320. }
  321. }
  322. return (ShellStatus);
  323. }
  324. /**
  325. Function to modify an option.
  326. @param[in] BcfgOperation Pointer to BCFG operation.
  327. @param[in] OrderCount The number if items in CurrentOrder.
  328. @retval SHELL_SUCCESS The operation was successful.
  329. @retval SHELL_INVALID_PARAMETER A parameter was invalid.
  330. @retval SHELL_OUT_OF_RESOUCES A memory allocation failed.
  331. **/
  332. SHELL_STATUS
  333. BcfgMod (
  334. IN CONST BGFG_OPERATION *BcfgOperation,
  335. IN CONST UINTN OrderCount
  336. )
  337. {
  338. EFI_STATUS Status;
  339. EFI_HANDLE CurHandle;
  340. SHELL_STATUS ShellStatus;
  341. CHAR16 OptionStr[40];
  342. EFI_SHELL_FILE_INFO *FileList;
  343. EFI_SHELL_FILE_INFO *Arg;
  344. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  345. EFI_DEVICE_PATH_PROTOCOL *DevicePathBuffer;
  346. EFI_DEVICE_PATH_PROTOCOL *DevicePathWalker;
  347. EFI_BOOT_MANAGER_LOAD_OPTION LoadOption;
  348. ShellStatus = SHELL_SUCCESS;
  349. FileList = NULL;
  350. DevicePath = NULL;
  351. DevicePathBuffer = NULL;
  352. ZeroMem (&LoadOption, sizeof(EFI_BOOT_MANAGER_LOAD_OPTION));
  353. if ( (BcfgOperation->Type == BcfgTypeMod && BcfgOperation->Description == NULL) ||
  354. (BcfgOperation->Type == BcfgTypeModf && BcfgOperation->FileName == NULL) ||
  355. (BcfgOperation->Type == BcfgTypeModp && BcfgOperation->FileName == NULL) ||
  356. (BcfgOperation->Type == BcfgTypeModh && BcfgOperation->HandleIndex == 0) ||
  357. (BcfgOperation->Number1 > OrderCount)
  358. ) {
  359. return (SHELL_INVALID_PARAMETER);
  360. }
  361. if (BcfgOperation->Type == BcfgTypeModh) {
  362. CurHandle = ConvertHandleIndexToHandle (BcfgOperation->HandleIndex);
  363. ShellStatus = GetDevicePathByHandle (CurHandle, BcfgOperation->Target, &DevicePathBuffer);
  364. if (ShellStatus == SHELL_SUCCESS) {
  365. DevicePath = DuplicateDevicePath (DevicePathBuffer);
  366. }
  367. } else if (BcfgOperation->Type == BcfgTypeModf || BcfgOperation->Type == BcfgTypeModp) {
  368. //
  369. // Get Device Path by FileName.
  370. //
  371. ShellOpenFileMetaArg ((CHAR16 *)BcfgOperation->FileName, EFI_FILE_MODE_READ, &FileList);
  372. if (FileList == NULL) {
  373. //
  374. // The name of file matched nothing.
  375. //
  376. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellBcfgHiiHandle, L"bcfg", BcfgOperation->FileName);
  377. ShellStatus = SHELL_INVALID_PARAMETER;
  378. }
  379. else if (FileList->Link.ForwardLink != FileList->Link.BackLink) {
  380. //
  381. // If the name of file expanded to multiple names, it's fail.
  382. //
  383. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellBcfgHiiHandle, L"bcfg", BcfgOperation->FileName);
  384. ShellStatus = SHELL_INVALID_PARAMETER;
  385. } else {
  386. Arg = (EFI_SHELL_FILE_INFO *)GetFirstNode (&FileList->Link);
  387. if (EFI_ERROR (Arg->Status)) {
  388. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellBcfgHiiHandle, L"bcfg", BcfgOperation->FileName);
  389. ShellStatus = SHELL_INVALID_PARAMETER;
  390. } else {
  391. DevicePathBuffer = gEfiShellProtocol->GetDevicePathFromFilePath (Arg->FullName);
  392. if (DevicePathBuffer == NULL) {
  393. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellBcfgHiiHandle, L"bcfg", Arg->FullName);
  394. ShellStatus = SHELL_UNSUPPORTED;
  395. }
  396. }
  397. }
  398. if (ShellStatus == SHELL_SUCCESS) {
  399. if (BcfgOperation->Type == BcfgTypeModp) {
  400. ShellStatus = SHELL_INVALID_PARAMETER;
  401. DevicePathWalker = DevicePathBuffer;
  402. while (!IsDevicePathEnd (DevicePathWalker)) {
  403. if ( DevicePathType (DevicePathWalker) == MEDIA_DEVICE_PATH &&
  404. DevicePathSubType (DevicePathWalker) == MEDIA_HARDDRIVE_DP
  405. ) {
  406. //
  407. // We found the portion of device path starting with the hard driver partition.
  408. //
  409. ShellStatus = SHELL_SUCCESS;
  410. DevicePath = DuplicateDevicePath (DevicePathWalker);
  411. break;
  412. } else {
  413. DevicePathWalker = NextDevicePathNode (DevicePathWalker);
  414. }
  415. }
  416. } else {
  417. DevicePath = DuplicateDevicePath (DevicePathBuffer);
  418. }
  419. FreePool (DevicePathBuffer);
  420. }
  421. }
  422. if (ShellStatus == SHELL_SUCCESS) {
  423. if (BcfgOperation->Target == BcfgTargetBootOrder) {
  424. UnicodeSPrint (OptionStr, sizeof (OptionStr), L"Boot%04x", BcfgOperation->Order[BcfgOperation->Number1]);
  425. } else {
  426. UnicodeSPrint (OptionStr, sizeof (OptionStr), L"Driver%04x", BcfgOperation->Order[BcfgOperation->Number1]);
  427. }
  428. Status = EfiBootManagerVariableToLoadOption (OptionStr, &LoadOption);
  429. if (EFI_ERROR(Status)) {
  430. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NONE), gShellBcfgHiiHandle);
  431. ShellStatus = SHELL_NOT_FOUND;
  432. }
  433. }
  434. if (ShellStatus == SHELL_SUCCESS) {
  435. if (BcfgOperation->Type == BcfgTypeMod) {
  436. SHELL_FREE_NON_NULL (LoadOption.Description);
  437. LoadOption.Description = AllocateCopyPool (StrSize (BcfgOperation->Description), BcfgOperation->Description);
  438. } else {
  439. SHELL_FREE_NON_NULL (LoadOption.FilePath);
  440. LoadOption.FilePath = DuplicateDevicePath (DevicePath);
  441. }
  442. Status = EfiBootManagerLoadOptionToVariable (&LoadOption);
  443. if (EFI_ERROR(Status)) {
  444. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", OptionStr);
  445. ShellStatus = SHELL_INVALID_PARAMETER;
  446. }
  447. }
  448. EfiBootManagerFreeLoadOption (&LoadOption);
  449. if (DevicePath != NULL) {
  450. FreePool (DevicePath);
  451. }
  452. if (FileList != NULL) {
  453. ShellCloseFileMetaArg (&FileList);
  454. }
  455. return (ShellStatus);
  456. }
  457. /**
  458. Function to add a option.
  459. @param[in] Position The position to add Target at.
  460. @param[in] File The file to make the target.
  461. @param[in] Desc The description text.
  462. @param[in] CurrentOrder The pointer to the current order of items.
  463. @param[in] OrderCount The number if items in CurrentOrder.
  464. @param[in] Target The info on the option to add.
  465. @param[in] UseHandle TRUE to use HandleNumber, FALSE to use File and Desc.
  466. @param[in] UsePath TRUE to convert to devicepath.
  467. @param[in] HandleNumber The handle number to add.
  468. @retval SHELL_SUCCESS The operation was successful.
  469. @retval SHELL_INVALID_PARAMETER A parameter was invalid.
  470. **/
  471. SHELL_STATUS
  472. BcfgAdd(
  473. IN UINTN Position,
  474. IN CONST CHAR16 *File,
  475. IN CONST CHAR16 *Desc,
  476. IN CONST UINT16 *CurrentOrder,
  477. IN CONST UINTN OrderCount,
  478. IN CONST BCFG_OPERATION_TARGET Target,
  479. IN CONST BOOLEAN UseHandle,
  480. IN CONST BOOLEAN UsePath,
  481. IN CONST UINTN HandleNumber
  482. )
  483. {
  484. EFI_STATUS Status;
  485. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  486. EFI_DEVICE_PATH_PROTOCOL *DevPath;
  487. EFI_DEVICE_PATH_PROTOCOL *FilePath;
  488. CHAR16 *Str;
  489. UINT8 *TempByteBuffer;
  490. UINT8 *TempByteStart;
  491. EFI_SHELL_FILE_INFO *Arg;
  492. EFI_SHELL_FILE_INFO *FileList;
  493. CHAR16 OptionStr[40];
  494. UINTN DescSize, FilePathSize;
  495. BOOLEAN Found;
  496. UINTN TargetLocation;
  497. UINTN Index;
  498. EFI_HANDLE *Handles;
  499. EFI_HANDLE CurHandle;
  500. UINTN DriverBindingHandleCount;
  501. UINTN ParentControllerHandleCount;
  502. UINTN ChildControllerHandleCount;
  503. SHELL_STATUS ShellStatus;
  504. UINT16 *NewOrder;
  505. if (!UseHandle) {
  506. if (File == NULL || Desc == NULL) {
  507. return (SHELL_INVALID_PARAMETER);
  508. }
  509. } else {
  510. if (HandleNumber == 0) {
  511. return (SHELL_INVALID_PARAMETER);
  512. }
  513. }
  514. if (Position > OrderCount) {
  515. Position = OrderCount;
  516. }
  517. Str = NULL;
  518. FilePath = NULL;
  519. FileList = NULL;
  520. Handles = NULL;
  521. ShellStatus = SHELL_SUCCESS;
  522. TargetLocation = 0xFFFF;
  523. if (UseHandle) {
  524. CurHandle = ConvertHandleIndexToHandle(HandleNumber);
  525. if (CurHandle == NULL) {
  526. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number");
  527. ShellStatus = SHELL_INVALID_PARAMETER;
  528. } else {
  529. if (Target == BcfgTargetBootOrder) {
  530. //
  531. //Make sure that the handle should point to a real controller
  532. //
  533. Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
  534. CurHandle,
  535. &DriverBindingHandleCount,
  536. NULL);
  537. Status = PARSE_HANDLE_DATABASE_PARENTS (
  538. CurHandle,
  539. &ParentControllerHandleCount,
  540. NULL);
  541. Status = ParseHandleDatabaseForChildControllers (
  542. CurHandle,
  543. &ChildControllerHandleCount,
  544. NULL);
  545. if (DriverBindingHandleCount > 0
  546. || ParentControllerHandleCount > 0
  547. || ChildControllerHandleCount > 0) {
  548. FilePath = NULL;
  549. Status = gBS->HandleProtocol (
  550. CurHandle,
  551. &gEfiDevicePathProtocolGuid,
  552. (VOID**)&FilePath);
  553. }
  554. if (EFI_ERROR (Status)) {
  555. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_HANDLE), gShellBcfgHiiHandle, L"bcfg", HandleNumber);
  556. ShellStatus = SHELL_INVALID_PARAMETER;
  557. }
  558. } else {
  559. //
  560. //Make sure that the handle should point to driver, not a controller.
  561. //
  562. Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
  563. CurHandle,
  564. &DriverBindingHandleCount,
  565. NULL);
  566. Status = PARSE_HANDLE_DATABASE_PARENTS (
  567. CurHandle,
  568. &ParentControllerHandleCount,
  569. NULL);
  570. Status = ParseHandleDatabaseForChildControllers (
  571. CurHandle,
  572. &ChildControllerHandleCount,
  573. NULL);
  574. Status = gBS->HandleProtocol (
  575. CurHandle,
  576. &gEfiDevicePathProtocolGuid,
  577. (VOID**)&FilePath);
  578. if (DriverBindingHandleCount > 0
  579. || ParentControllerHandleCount > 0
  580. || ChildControllerHandleCount > 0
  581. || !EFI_ERROR(Status) ) {
  582. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number");
  583. ShellStatus = SHELL_INVALID_PARAMETER;
  584. } else {
  585. //
  586. // Get the DevicePath from the loaded image information.
  587. //
  588. Status = GetDevicePathForDriverHandle(CurHandle, &FilePath);
  589. }
  590. }
  591. }
  592. } else {
  593. //
  594. // Get file info
  595. //
  596. ShellOpenFileMetaArg ((CHAR16*)File, EFI_FILE_MODE_READ, &FileList);
  597. if (FileList == NULL) {
  598. //
  599. // If filename matched nothing fail
  600. //
  601. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellBcfgHiiHandle, L"bcfg", File);
  602. ShellStatus = SHELL_INVALID_PARAMETER;
  603. } else if (FileList->Link.ForwardLink != FileList->Link.BackLink) {
  604. //
  605. // If filename expanded to multiple names, fail
  606. //
  607. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellBcfgHiiHandle, L"bcfg", File);
  608. ShellStatus = SHELL_INVALID_PARAMETER;
  609. } else {
  610. Arg = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link);
  611. if (EFI_ERROR(Arg->Status)) {
  612. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellBcfgHiiHandle, L"bcfg", File);
  613. ShellStatus = SHELL_INVALID_PARAMETER;
  614. } else {
  615. //
  616. // Build FilePath to the filename
  617. //
  618. //
  619. // get the device path
  620. //
  621. DevicePath = gEfiShellProtocol->GetDevicePathFromFilePath(Arg->FullName);
  622. if (DevicePath == NULL) {
  623. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellBcfgHiiHandle, L"bcfg", Arg->FullName);
  624. ShellStatus = SHELL_UNSUPPORTED;
  625. } else {
  626. if (UsePath) {
  627. DevPath = DevicePath;
  628. ShellStatus = SHELL_INVALID_PARAMETER;
  629. while (!IsDevicePathEnd(DevPath)) {
  630. if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) &&
  631. (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) {
  632. //
  633. // If we find it use it instead
  634. //
  635. ShellStatus = SHELL_SUCCESS;
  636. FilePath = DuplicateDevicePath (DevPath);
  637. break;
  638. }
  639. DevPath = NextDevicePathNode(DevPath);
  640. }
  641. } else {
  642. FilePath = DuplicateDevicePath(DevicePath);
  643. }
  644. FreePool(DevicePath);
  645. }
  646. }
  647. }
  648. }
  649. if (ShellStatus == SHELL_SUCCESS) {
  650. //
  651. // Find a free target ,a brute force implementation
  652. //
  653. Found = FALSE;
  654. for (TargetLocation=0; TargetLocation < 0xFFFF; TargetLocation++) {
  655. Found = TRUE;
  656. for (Index=0; Index < OrderCount; Index++) {
  657. if (CurrentOrder[Index] == TargetLocation) {
  658. Found = FALSE;
  659. break;
  660. }
  661. }
  662. if (Found) {
  663. break;
  664. }
  665. }
  666. if (TargetLocation == 0xFFFF) {
  667. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET_NF), gShellBcfgHiiHandle, L"bcfg");
  668. } else {
  669. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET), gShellBcfgHiiHandle, TargetLocation);
  670. }
  671. }
  672. if (ShellStatus == SHELL_SUCCESS) {
  673. //
  674. // Add the option
  675. //
  676. DescSize = StrSize(Desc);
  677. FilePathSize = GetDevicePathSize (FilePath);
  678. TempByteBuffer = AllocateZeroPool(sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize);
  679. if (TempByteBuffer != NULL) {
  680. TempByteStart = TempByteBuffer;
  681. *((UINT32 *) TempByteBuffer) = LOAD_OPTION_ACTIVE; // Attributes
  682. TempByteBuffer += sizeof (UINT32);
  683. *((UINT16 *) TempByteBuffer) = (UINT16)FilePathSize; // FilePathListLength
  684. TempByteBuffer += sizeof (UINT16);
  685. CopyMem (TempByteBuffer, Desc, DescSize);
  686. TempByteBuffer += DescSize;
  687. ASSERT (FilePath != NULL);
  688. CopyMem (TempByteBuffer, FilePath, FilePathSize);
  689. UnicodeSPrint (OptionStr, sizeof(OptionStr), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", TargetLocation);
  690. Status = gRT->SetVariable (
  691. OptionStr,
  692. &gEfiGlobalVariableGuid,
  693. EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
  694. sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize,
  695. TempByteStart
  696. );
  697. FreePool(TempByteStart);
  698. } else {
  699. Status = EFI_OUT_OF_RESOURCES;
  700. }
  701. if (EFI_ERROR(Status)) {
  702. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", OptionStr);
  703. } else {
  704. NewOrder = AllocateZeroPool ((OrderCount + 1) * sizeof (NewOrder[0]));
  705. if (NewOrder != NULL) {
  706. CopyMem (NewOrder, CurrentOrder, (OrderCount) * sizeof (NewOrder[0]));
  707. //
  708. // Insert target into order list
  709. //
  710. for (Index = OrderCount; Index > Position; Index--) {
  711. NewOrder[Index] = NewOrder[Index - 1];
  712. }
  713. NewOrder[Position] = (UINT16) TargetLocation;
  714. Status = gRT->SetVariable (
  715. Target == BcfgTargetBootOrder ? L"BootOrder" : L"DriverOrder",
  716. &gEfiGlobalVariableGuid,
  717. EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
  718. (OrderCount + 1) * sizeof (UINT16),
  719. NewOrder
  720. );
  721. FreePool (NewOrder);
  722. if (EFI_ERROR (Status)) {
  723. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder ? L"BootOrder" : L"DriverOrder");
  724. ShellStatus = SHELL_INVALID_PARAMETER;
  725. } else {
  726. Print (L"bcfg: Add %s as %x\n", OptionStr, Position);
  727. }
  728. }
  729. }
  730. }
  731. //
  732. //If always Free FilePath, will free devicepath in system when use "addh"
  733. //
  734. if (FilePath!=NULL && !UseHandle) {
  735. FreePool (FilePath);
  736. }
  737. if (Str != NULL) {
  738. FreePool(Str);
  739. }
  740. if (Handles != NULL) {
  741. FreePool (Handles);
  742. }
  743. if (FileList != NULL) {
  744. ShellCloseFileMetaArg (&FileList);
  745. }
  746. return (ShellStatus);
  747. }
  748. /**
  749. Funciton to remove an item.
  750. @param[in] Target The target item to move.
  751. @param[in] CurrentOrder The pointer to the current order of items.
  752. @param[in] OrderCount The number if items in CurrentOrder.
  753. @param[in] Location The current location of the Target.
  754. @retval SHELL_SUCCESS The operation was successful.
  755. @retval SHELL_INVALID_PARAMETER A parameter was invalid.
  756. **/
  757. SHELL_STATUS
  758. BcfgRemove(
  759. IN CONST BCFG_OPERATION_TARGET Target,
  760. IN CONST UINT16 *CurrentOrder,
  761. IN CONST UINTN OrderCount,
  762. IN CONST UINT16 Location
  763. )
  764. {
  765. CHAR16 VariableName[12];
  766. UINT16 *NewOrder;
  767. EFI_STATUS Status;
  768. UINTN NewCount;
  769. UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", CurrentOrder[Location]);
  770. Status = gRT->SetVariable(
  771. VariableName,
  772. (EFI_GUID*)&gEfiGlobalVariableGuid,
  773. EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
  774. 0,
  775. NULL);
  776. if (EFI_ERROR(Status)) {
  777. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
  778. return (SHELL_INVALID_PARAMETER);
  779. }
  780. NewOrder = AllocateZeroPool(OrderCount*sizeof(CurrentOrder[0]));
  781. if (NewOrder != NULL) {
  782. NewCount = OrderCount;
  783. CopyMem(NewOrder, CurrentOrder, OrderCount*sizeof(CurrentOrder[0]));
  784. CopyMem(NewOrder+Location, NewOrder+Location+1, (OrderCount - Location - 1)*sizeof(CurrentOrder[0]));
  785. NewCount--;
  786. Status = gRT->SetVariable(
  787. Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
  788. (EFI_GUID*)&gEfiGlobalVariableGuid,
  789. EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
  790. NewCount*sizeof(NewOrder[0]),
  791. NewOrder);
  792. FreePool(NewOrder);
  793. } else {
  794. Status = EFI_OUT_OF_RESOURCES;
  795. }
  796. if (EFI_ERROR(Status)) {
  797. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder");
  798. return (SHELL_INVALID_PARAMETER);
  799. }
  800. return (SHELL_SUCCESS);
  801. }
  802. /**
  803. Funciton to move a item to another location.
  804. @param[in] Target The target item to move.
  805. @param[in] CurrentOrder The pointer to the current order of items.
  806. @param[in] OrderCount The number if items in CurrentOrder.
  807. @param[in] OldLocation The current location of the Target.
  808. @param[in] NewLocation The desired location of the Target.
  809. @retval SHELL_SUCCESS The operation was successful.
  810. @retval SHELL_INVALID_PARAMETER A parameter was invalid.
  811. **/
  812. SHELL_STATUS
  813. BcfgMove(
  814. IN CONST BCFG_OPERATION_TARGET Target,
  815. IN CONST UINT16 *CurrentOrder,
  816. IN CONST UINTN OrderCount,
  817. IN CONST UINT16 OldLocation,
  818. IN UINT16 NewLocation
  819. )
  820. {
  821. UINT16 *NewOrder;
  822. EFI_STATUS Status;
  823. UINT16 Temp;
  824. NewOrder = AllocateCopyPool(OrderCount*sizeof(CurrentOrder[0]), CurrentOrder);
  825. if (NewOrder == NULL) {
  826. return (SHELL_OUT_OF_RESOURCES);
  827. }
  828. //
  829. // correct the new location
  830. //
  831. if (NewLocation >= OrderCount) {
  832. if (OrderCount > 0) {
  833. NewLocation = (UINT16)OrderCount - 1;
  834. } else {
  835. NewLocation = 0;
  836. }
  837. }
  838. Temp = CurrentOrder[OldLocation];
  839. CopyMem(NewOrder+OldLocation, NewOrder+OldLocation+1, (OrderCount - OldLocation - 1)*sizeof(CurrentOrder[0]));
  840. CopyMem(NewOrder+NewLocation+1, NewOrder+NewLocation, (OrderCount - NewLocation - 1)*sizeof(CurrentOrder[0]));
  841. NewOrder[NewLocation] = Temp;
  842. Status = gRT->SetVariable(
  843. Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
  844. (EFI_GUID*)&gEfiGlobalVariableGuid,
  845. EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
  846. OrderCount*sizeof(CurrentOrder[0]),
  847. NewOrder);
  848. FreePool(NewOrder);
  849. if (EFI_ERROR(Status)) {
  850. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder");
  851. return (SHELL_INVALID_PARAMETER);
  852. }
  853. return (SHELL_SUCCESS);
  854. }
  855. /**
  856. Function to add optional data to an option.
  857. @param[in] OptData The optional data to add.
  858. @param[in] CurrentOrder The pointer to the current order of items.
  859. @param[in] OrderCount The number if items in CurrentOrder.
  860. @param[in] Target The target of the operation.
  861. @retval SHELL_SUCCESS The operation was succesful.
  862. **/
  863. SHELL_STATUS
  864. BcfgAddOpt(
  865. IN CONST CHAR16 *OptData,
  866. IN CONST UINT16 *CurrentOrder,
  867. IN CONST UINTN OrderCount,
  868. IN CONST BCFG_OPERATION_TARGET Target
  869. )
  870. {
  871. EFI_KEY_OPTION NewKeyOption;
  872. EFI_KEY_OPTION *KeyOptionBuffer;
  873. SHELL_STATUS ShellStatus;
  874. EFI_STATUS Status;
  875. UINT16 OptionIndex;
  876. UINT16 LoopCounter;
  877. UINT64 Intermediate;
  878. CONST CHAR16 *Temp;
  879. CONST CHAR16 *Walker;
  880. CHAR16 *FileName;
  881. CHAR16 *Temp2;
  882. CHAR16 *Data;
  883. UINT32 KeyIndex;
  884. CHAR16 VariableName[12];
  885. VOID *VariableData;
  886. SHELL_FILE_HANDLE FileHandle;
  887. Status = EFI_SUCCESS;
  888. ShellStatus = SHELL_SUCCESS;
  889. Walker = OptData;
  890. FileName = NULL;
  891. Data = NULL;
  892. KeyOptionBuffer = NULL;
  893. VariableData = NULL;
  894. ZeroMem(&NewKeyOption, sizeof(EFI_KEY_OPTION));
  895. ZeroMem(VariableName, sizeof(VariableName));
  896. while(Walker[0] == L' ') {
  897. Walker++;
  898. }
  899. //
  900. // Get the index of the variable we are changing.
  901. //
  902. Status = ShellConvertStringToUint64(Walker, &Intermediate, TRUE, TRUE);
  903. if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL || ((UINT16)Intermediate) > ((UINT16)OrderCount)) {
  904. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Option Index");
  905. ShellStatus = SHELL_INVALID_PARAMETER;
  906. return (ShellStatus);
  907. }
  908. OptionIndex = (UINT16)Intermediate;
  909. Temp = StrStr(Walker, L" ");
  910. if (Temp != NULL) {
  911. Walker = Temp;
  912. }
  913. while(Walker[0] == L' ') {
  914. Walker++;
  915. }
  916. //
  917. // determine whether we have file with data, quote delimited information, or a hot-key
  918. //
  919. if (Walker[0] == L'\"') {
  920. //
  921. // quoted filename or quoted information.
  922. //
  923. Temp = StrStr(Walker+1, L"\"");
  924. if (Temp == NULL || StrLen(Temp) != 1) {
  925. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
  926. ShellStatus = SHELL_INVALID_PARAMETER;
  927. } else {
  928. FileName = StrnCatGrow(&FileName, NULL, Walker+1, 0);
  929. if (FileName == NULL) {
  930. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellBcfgHiiHandle, L"bcfg");
  931. ShellStatus = SHELL_OUT_OF_RESOURCES;
  932. return (ShellStatus);
  933. }
  934. Temp2 = StrStr(FileName, L"\"");
  935. ASSERT(Temp2 != NULL);
  936. Temp2[0] = CHAR_NULL;
  937. Temp2++;
  938. if (StrLen(Temp2)>0) {
  939. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
  940. ShellStatus = SHELL_INVALID_PARAMETER;
  941. }
  942. if (EFI_ERROR(ShellFileExists(Walker))) {
  943. //
  944. // Not a file. must be misc information.
  945. //
  946. Data = FileName;
  947. FileName = NULL;
  948. } else {
  949. FileName = StrnCatGrow(&FileName, NULL, Walker, 0);
  950. }
  951. }
  952. } else {
  953. //
  954. // filename or hot key information.
  955. //
  956. if (StrStr(Walker, L" ") == NULL) {
  957. //
  958. // filename
  959. //
  960. if (EFI_ERROR(ShellFileExists(Walker))) {
  961. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FIND_FAIL), gShellBcfgHiiHandle, L"bcfg", Walker);
  962. ShellStatus = SHELL_INVALID_PARAMETER;
  963. } else {
  964. FileName = StrnCatGrow(&FileName, NULL, Walker, 0);
  965. }
  966. } else {
  967. if (Target != BcfgTargetBootOrder) {
  968. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_BOOT_ONLY), gShellBcfgHiiHandle, L"bcfg");
  969. ShellStatus = SHELL_INVALID_PARAMETER;
  970. }
  971. if (ShellStatus == SHELL_SUCCESS) {
  972. //
  973. // Get hot key information
  974. //
  975. Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);
  976. if (EFI_ERROR(Status) || (((UINT32)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL) {
  977. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
  978. ShellStatus = SHELL_INVALID_PARAMETER;
  979. }
  980. NewKeyOption.KeyData.PackedValue = (UINT32)Intermediate;
  981. Temp = StrStr(Walker, L" ");
  982. if (Temp != NULL) {
  983. Walker = Temp;
  984. }
  985. while(Walker[0] == L' ') {
  986. Walker++;
  987. }
  988. }
  989. if (ShellStatus == SHELL_SUCCESS) {
  990. //
  991. // Now we know how many EFI_INPUT_KEY structs we need to attach to the end of the EFI_KEY_OPTION struct.
  992. // Re-allocate with the added information.
  993. //
  994. KeyOptionBuffer = AllocatePool (sizeof(EFI_KEY_OPTION) + (sizeof(EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount));
  995. if (KeyOptionBuffer == NULL) {
  996. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle, L"bcfg");
  997. ShellStatus = SHELL_OUT_OF_RESOURCES;
  998. return ShellStatus;
  999. }
  1000. CopyMem (KeyOptionBuffer, &NewKeyOption, sizeof(EFI_KEY_OPTION));
  1001. }
  1002. for (LoopCounter = 0 ; ShellStatus == SHELL_SUCCESS && LoopCounter < NewKeyOption.KeyData.Options.InputKeyCount; LoopCounter++) {
  1003. //
  1004. // ScanCode
  1005. //
  1006. Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);
  1007. if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL) {
  1008. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
  1009. ShellStatus = SHELL_INVALID_PARAMETER;
  1010. }
  1011. ((EFI_INPUT_KEY*)(((UINT8*)KeyOptionBuffer) + sizeof(EFI_KEY_OPTION)))[LoopCounter].ScanCode = (UINT16)Intermediate;
  1012. Temp = StrStr(Walker, L" ");
  1013. if (Temp != NULL) {
  1014. Walker = Temp;
  1015. }
  1016. while(Walker[0] == L' ') {
  1017. Walker++;
  1018. }
  1019. //
  1020. // UnicodeChar
  1021. //
  1022. Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);
  1023. if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate)) {
  1024. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
  1025. ShellStatus = SHELL_INVALID_PARAMETER;
  1026. }
  1027. ((EFI_INPUT_KEY*)(((UINT8*)KeyOptionBuffer) + sizeof(EFI_KEY_OPTION)))[LoopCounter].UnicodeChar = (UINT16)Intermediate;
  1028. Temp = StrStr(Walker, L" ");
  1029. if (Temp != NULL) {
  1030. Walker = Temp;
  1031. }
  1032. while(Walker[0] == L' ') {
  1033. Walker++;
  1034. }
  1035. }
  1036. if (ShellStatus == SHELL_SUCCESS) {
  1037. //
  1038. // Now do the BootOption / BootOptionCrc
  1039. //
  1040. ASSERT (OptionIndex <= OrderCount);
  1041. KeyOptionBuffer->BootOption = CurrentOrder[OptionIndex];
  1042. Status = GetBootOptionCrc(&(KeyOptionBuffer->BootOptionCrc), KeyOptionBuffer->BootOption);
  1043. if (EFI_ERROR(Status)) {
  1044. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Option Index");
  1045. ShellStatus = SHELL_INVALID_PARAMETER;
  1046. }
  1047. }
  1048. if (ShellStatus == SHELL_SUCCESS) {
  1049. for (Temp2 = NULL, KeyIndex = 0 ; KeyIndex <= 0xFFFF ; KeyIndex++) {
  1050. UnicodeSPrint(VariableName, sizeof(VariableName), L"Key%04x", KeyIndex);
  1051. Status = GetEfiGlobalVariable2 (VariableName, &VariableData, NULL);
  1052. if (Status == EFI_NOT_FOUND) {
  1053. break;
  1054. }
  1055. if (!EFI_ERROR(Status)) {
  1056. SHELL_FREE_NON_NULL(VariableData);
  1057. }
  1058. }
  1059. if (KeyIndex <= 0xFFFF) {
  1060. Status = gRT->SetVariable(
  1061. VariableName,
  1062. (EFI_GUID*)&gEfiGlobalVariableGuid,
  1063. EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
  1064. sizeof(EFI_KEY_OPTION) + (sizeof(EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount),
  1065. KeyOptionBuffer);
  1066. if (EFI_ERROR(Status)) {
  1067. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
  1068. ShellStatus = SHELL_INVALID_PARAMETER;
  1069. }
  1070. } else {
  1071. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_VAR_NO_NUM), gShellBcfgHiiHandle, L"bcfg");
  1072. ShellStatus = SHELL_INVALID_PARAMETER;
  1073. }
  1074. ASSERT(FileName == NULL && Data == NULL);
  1075. }
  1076. }
  1077. }
  1078. //
  1079. // Shouldn't be possible to have have both. Neither is ok though.
  1080. //
  1081. ASSERT(FileName == NULL || Data == NULL);
  1082. if (ShellStatus == SHELL_SUCCESS && (FileName != NULL || Data != NULL)) {
  1083. if (FileName != NULL) {
  1084. //
  1085. // Open the file and populate the data buffer.
  1086. //
  1087. Status = ShellOpenFileByName(
  1088. FileName,
  1089. &FileHandle,
  1090. EFI_FILE_MODE_READ,
  1091. 0);
  1092. if (!EFI_ERROR(Status)) {
  1093. Status = ShellGetFileSize(FileHandle, &Intermediate);
  1094. }
  1095. Data = AllocateZeroPool((UINTN)Intermediate);
  1096. if (Data == NULL) {
  1097. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle, L"bcfg");
  1098. ShellStatus = SHELL_OUT_OF_RESOURCES;
  1099. }
  1100. if (!EFI_ERROR(Status)) {
  1101. Status = ShellReadFile(FileHandle, (UINTN *)&Intermediate, Data);
  1102. }
  1103. } else {
  1104. Intermediate = StrSize(Data);
  1105. }
  1106. if (!EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS && Data != NULL) {
  1107. Status = UpdateOptionalData(CurrentOrder[OptionIndex], (UINTN)Intermediate, (UINT8*)Data, Target);
  1108. if (EFI_ERROR(Status)) {
  1109. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
  1110. ShellStatus = SHELL_INVALID_PARAMETER;
  1111. }
  1112. }
  1113. if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {
  1114. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
  1115. ShellStatus = SHELL_INVALID_PARAMETER;
  1116. }
  1117. }
  1118. SHELL_FREE_NON_NULL(Data);
  1119. SHELL_FREE_NON_NULL(KeyOptionBuffer);
  1120. SHELL_FREE_NON_NULL(FileName);
  1121. return ShellStatus;
  1122. }
  1123. /**
  1124. Function to dump the Bcfg information.
  1125. @param[in] Op The operation.
  1126. @param[in] OrderCount How many to dump.
  1127. @param[in] CurrentOrder The pointer to the current order of items.
  1128. @param[in] VerboseOutput TRUE for extra output. FALSE otherwise.
  1129. @retval SHELL_SUCCESS The dump was successful.
  1130. @retval SHELL_INVALID_PARAMETER A parameter was invalid.
  1131. **/
  1132. SHELL_STATUS
  1133. BcfgDisplayDump(
  1134. IN CONST CHAR16 *Op,
  1135. IN CONST UINTN OrderCount,
  1136. IN CONST UINT16 *CurrentOrder,
  1137. IN CONST BOOLEAN VerboseOutput
  1138. )
  1139. {
  1140. EFI_STATUS Status;
  1141. UINT8 *Buffer;
  1142. UINTN BufferSize;
  1143. CHAR16 VariableName[12];
  1144. UINTN LoopVar;
  1145. CHAR16 *DevPathString;
  1146. VOID *FilePathList;
  1147. UINTN Errors;
  1148. EFI_LOAD_OPTION *LoadOption;
  1149. CHAR16 *Description;
  1150. UINTN DescriptionSize;
  1151. UINTN OptionalDataOffset;
  1152. if (OrderCount == 0) {
  1153. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_BCFG_NONE), gShellBcfgHiiHandle, L"bcfg");
  1154. return (SHELL_SUCCESS);
  1155. }
  1156. Errors = 0;
  1157. for (LoopVar = 0 ; LoopVar < OrderCount ; LoopVar++) {
  1158. Buffer = NULL;
  1159. BufferSize = 0;
  1160. DevPathString = NULL;
  1161. UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Op, CurrentOrder[LoopVar]);
  1162. Status = gRT->GetVariable(
  1163. VariableName,
  1164. (EFI_GUID*)&gEfiGlobalVariableGuid,
  1165. NULL,
  1166. &BufferSize,
  1167. Buffer);
  1168. if (Status == EFI_BUFFER_TOO_SMALL) {
  1169. Buffer = AllocateZeroPool(BufferSize);
  1170. Status = gRT->GetVariable(
  1171. VariableName,
  1172. (EFI_GUID*)&gEfiGlobalVariableGuid,
  1173. NULL,
  1174. &BufferSize,
  1175. Buffer);
  1176. }
  1177. if (EFI_ERROR(Status) || Buffer == NULL) {
  1178. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_READ_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
  1179. ++Errors;
  1180. goto Cleanup;
  1181. }
  1182. //
  1183. // We expect the Attributes, FilePathListLength, and L'\0'-terminated
  1184. // Description fields to be present.
  1185. //
  1186. if (BufferSize < sizeof *LoadOption + sizeof (CHAR16)) {
  1187. ShellPrintHiiEx (
  1188. -1,
  1189. -1,
  1190. NULL,
  1191. STRING_TOKEN (STR_BCFG_VAR_CORRUPT),
  1192. gShellBcfgHiiHandle,
  1193. L"bcfg",
  1194. VariableName
  1195. );
  1196. ++Errors;
  1197. goto Cleanup;
  1198. }
  1199. LoadOption = (EFI_LOAD_OPTION *)Buffer;
  1200. Description = (CHAR16*)(Buffer + sizeof (EFI_LOAD_OPTION));
  1201. DescriptionSize = StrSize (Description);
  1202. if (LoadOption->FilePathListLength != 0) {
  1203. FilePathList = (UINT8 *)Description + DescriptionSize;
  1204. DevPathString = ConvertDevicePathToText(FilePathList, TRUE, FALSE);
  1205. }
  1206. OptionalDataOffset = sizeof *LoadOption + DescriptionSize +
  1207. LoadOption->FilePathListLength;
  1208. ShellPrintHiiEx(
  1209. -1,
  1210. -1,
  1211. NULL,
  1212. STRING_TOKEN(STR_BCFG_LOAD_OPTIONS),
  1213. gShellBcfgHiiHandle,
  1214. LoopVar,
  1215. VariableName,
  1216. Description,
  1217. DevPathString,
  1218. OptionalDataOffset >= BufferSize ? L'N' : L'Y'
  1219. );
  1220. if (VerboseOutput && (OptionalDataOffset < BufferSize)) {
  1221. DumpHex (
  1222. 2, // Indent
  1223. 0, // Offset (displayed)
  1224. BufferSize - OptionalDataOffset, // DataSize
  1225. Buffer + OptionalDataOffset // UserData
  1226. );
  1227. }
  1228. Cleanup:
  1229. if (Buffer != NULL) {
  1230. FreePool(Buffer);
  1231. }
  1232. if (DevPathString != NULL) {
  1233. FreePool(DevPathString);
  1234. }
  1235. }
  1236. return (Errors > 0) ? SHELL_INVALID_PARAMETER : SHELL_SUCCESS;
  1237. }
  1238. /**
  1239. Function to initialize the BCFG operation structure.
  1240. @param[in] Struct The stuct to initialize.
  1241. **/
  1242. VOID
  1243. InitBcfgStruct(
  1244. IN BGFG_OPERATION *Struct
  1245. )
  1246. {
  1247. ASSERT(Struct != NULL);
  1248. Struct->Target = BcfgTargetMax;
  1249. Struct->Type = BcfgTypeMax;
  1250. Struct->Number1 = 0;
  1251. Struct->Number2 = 0;
  1252. Struct->HandleIndex = 0;
  1253. Struct->FileName = NULL;
  1254. Struct->Description = NULL;
  1255. Struct->Order = NULL;
  1256. Struct->OptData = NULL;
  1257. }
  1258. STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
  1259. {L"-v", TypeFlag},
  1260. {L"-opt", TypeMaxValue},
  1261. {NULL, TypeMax}
  1262. };
  1263. /**
  1264. Function for 'bcfg' command.
  1265. @param[in] ImageHandle Handle to the Image (NULL if Internal).
  1266. @param[in] SystemTable Pointer to the System Table (NULL if Internal).
  1267. **/
  1268. SHELL_STATUS
  1269. EFIAPI
  1270. ShellCommandRunBcfg (
  1271. IN EFI_HANDLE ImageHandle,
  1272. IN EFI_SYSTEM_TABLE *SystemTable
  1273. )
  1274. {
  1275. EFI_STATUS Status;
  1276. LIST_ENTRY *Package;
  1277. CHAR16 *ProblemParam;
  1278. SHELL_STATUS ShellStatus;
  1279. UINTN ParamNumber;
  1280. CONST CHAR16 *CurrentParam;
  1281. BGFG_OPERATION CurrentOperation;
  1282. UINTN Length;
  1283. UINT64 Intermediate;
  1284. UINT16 Count;
  1285. Length = 0;
  1286. ProblemParam = NULL;
  1287. Package = NULL;
  1288. ShellStatus = SHELL_SUCCESS;
  1289. InitBcfgStruct(&CurrentOperation);
  1290. //
  1291. // initialize the shell lib (we must be in non-auto-init...)
  1292. //
  1293. Status = ShellInitialize();
  1294. ASSERT_EFI_ERROR(Status);
  1295. Status = CommandInit();
  1296. ASSERT_EFI_ERROR(Status);
  1297. //
  1298. // parse the command line
  1299. //
  1300. Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
  1301. if (EFI_ERROR(Status)) {
  1302. if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
  1303. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, L"bcfg", ProblemParam);
  1304. FreePool(ProblemParam);
  1305. ShellStatus = SHELL_INVALID_PARAMETER;
  1306. } else {
  1307. ASSERT(FALSE);
  1308. }
  1309. } else {
  1310. //
  1311. // Read in if we are doing -OPT
  1312. //
  1313. if (ShellCommandLineGetFlag(Package, L"-opt")) {
  1314. CurrentOperation.OptData = ShellCommandLineGetValue(Package, L"-opt");
  1315. if (CurrentOperation.OptData == NULL) {
  1316. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellBcfgHiiHandle, L"bcfg", L"-opt");
  1317. ShellStatus = SHELL_INVALID_PARAMETER;
  1318. }
  1319. CurrentOperation.Type = BcfgTypeOpt;
  1320. }
  1321. //
  1322. // small block to read the target of the operation
  1323. //
  1324. if ((ShellCommandLineGetCount(Package) < 3 && CurrentOperation.Type != BcfgTypeOpt) ||
  1325. (ShellCommandLineGetCount(Package) < 2 && CurrentOperation.Type == BcfgTypeOpt)
  1326. ){
  1327. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
  1328. ShellStatus = SHELL_INVALID_PARAMETER;
  1329. } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"driver") == 0) {
  1330. CurrentOperation.Target = BcfgTargetDriverOrder;
  1331. } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"boot") == 0) {
  1332. CurrentOperation.Target = BcfgTargetBootOrder;
  1333. } else {
  1334. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_DRIVER_BOOT), gShellBcfgHiiHandle, L"bcfg");
  1335. ShellStatus = SHELL_INVALID_PARAMETER;
  1336. }
  1337. //
  1338. // Read in the boot or driver order environment variable (not needed for opt)
  1339. //
  1340. if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) {
  1341. Length = 0;
  1342. Status = gRT->GetVariable(
  1343. CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
  1344. (EFI_GUID*)&gEfiGlobalVariableGuid,
  1345. NULL,
  1346. &Length,
  1347. CurrentOperation.Order);
  1348. if (Status == EFI_BUFFER_TOO_SMALL) {
  1349. CurrentOperation.Order = AllocateZeroPool(Length+(4*sizeof(CurrentOperation.Order[0])));
  1350. if (CurrentOperation.Order == NULL) {
  1351. ShellStatus = SHELL_OUT_OF_RESOURCES;
  1352. } else {
  1353. Status = gRT->GetVariable(
  1354. CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
  1355. (EFI_GUID*)&gEfiGlobalVariableGuid,
  1356. NULL,
  1357. &Length,
  1358. CurrentOperation.Order);
  1359. }
  1360. }
  1361. }
  1362. Count = (UINT16) (Length / sizeof(CurrentOperation.Order[0]));
  1363. //
  1364. // large block to read the type of operation and verify parameter types for the info.
  1365. //
  1366. if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) {
  1367. for (ParamNumber = 2 ; ParamNumber < ShellCommandLineGetCount(Package) && ShellStatus == SHELL_SUCCESS; ParamNumber++) {
  1368. CurrentParam = ShellCommandLineGetRawValue(Package, ParamNumber);
  1369. if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"dump") == 0) {
  1370. CurrentOperation.Type = BcfgTypeDump;
  1371. if (ShellCommandLineGetCount(Package) > 3) {
  1372. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellBcfgHiiHandle, L"bcfg");
  1373. ShellStatus = SHELL_INVALID_PARAMETER;
  1374. }
  1375. } else if (ShellCommandLineGetFlag(Package, L"-v")) {
  1376. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"-v (without dump)");
  1377. ShellStatus = SHELL_INVALID_PARAMETER;
  1378. } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"add") == 0) {
  1379. if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {
  1380. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
  1381. ShellStatus = SHELL_INVALID_PARAMETER;
  1382. }
  1383. CurrentOperation.Type = BcfgTypeAdd;
  1384. CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
  1385. if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
  1386. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
  1387. ShellStatus = SHELL_INVALID_PARAMETER;
  1388. } else {
  1389. Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
  1390. CurrentOperation.Number1 = (UINT16)Intermediate;
  1391. ASSERT(CurrentOperation.FileName == NULL);
  1392. CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
  1393. ASSERT(CurrentOperation.Description == NULL);
  1394. CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
  1395. }
  1396. } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addp") == 0) {
  1397. if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {
  1398. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
  1399. ShellStatus = SHELL_INVALID_PARAMETER;
  1400. }
  1401. CurrentOperation.Type = BcfgTypeAddp;
  1402. CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
  1403. if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
  1404. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
  1405. ShellStatus = SHELL_INVALID_PARAMETER;
  1406. } else {
  1407. Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
  1408. CurrentOperation.Number1 = (UINT16)Intermediate;
  1409. ASSERT(CurrentOperation.FileName == NULL);
  1410. CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
  1411. ASSERT(CurrentOperation.Description == NULL);
  1412. CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
  1413. }
  1414. } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addh") == 0) {
  1415. if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {
  1416. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
  1417. ShellStatus = SHELL_INVALID_PARAMETER;
  1418. }
  1419. CurrentOperation.Type = BcfgTypeAddh;
  1420. CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
  1421. if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
  1422. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
  1423. ShellStatus = SHELL_INVALID_PARAMETER;
  1424. } else {
  1425. Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
  1426. CurrentOperation.Number1 = (UINT16)Intermediate;
  1427. CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
  1428. if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
  1429. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
  1430. ShellStatus = SHELL_INVALID_PARAMETER;
  1431. } else {
  1432. Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
  1433. CurrentOperation.HandleIndex = (UINT16)Intermediate;
  1434. ASSERT(CurrentOperation.Description == NULL);
  1435. CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
  1436. }
  1437. }
  1438. } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"rm") == 0) {
  1439. if ((ParamNumber + 1) >= ShellCommandLineGetCount(Package)) {
  1440. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
  1441. ShellStatus = SHELL_INVALID_PARAMETER;
  1442. }
  1443. CurrentOperation.Type = BcfgTypeRm;
  1444. CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
  1445. if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
  1446. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
  1447. ShellStatus = SHELL_INVALID_PARAMETER;
  1448. } else {
  1449. Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
  1450. CurrentOperation.Number1 = (UINT16)Intermediate;
  1451. if (CurrentOperation.Number1 >= Count){
  1452. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
  1453. ShellStatus = SHELL_INVALID_PARAMETER;
  1454. }
  1455. }
  1456. } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"mv") == 0) {
  1457. if ((ParamNumber + 2) >= ShellCommandLineGetCount(Package)) {
  1458. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
  1459. ShellStatus = SHELL_INVALID_PARAMETER;
  1460. }
  1461. CurrentOperation.Type = BcfgTypeMv;
  1462. CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
  1463. if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
  1464. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
  1465. ShellStatus = SHELL_INVALID_PARAMETER;
  1466. } else {
  1467. Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
  1468. CurrentOperation.Number1 = (UINT16)Intermediate;
  1469. if (CurrentOperation.Number1 >= Count){
  1470. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
  1471. ShellStatus = SHELL_INVALID_PARAMETER;
  1472. } else {
  1473. CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
  1474. if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
  1475. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
  1476. ShellStatus = SHELL_INVALID_PARAMETER;
  1477. } else {
  1478. Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
  1479. CurrentOperation.Number2 = (UINT16)Intermediate;
  1480. }
  1481. if (CurrentOperation.Number2 == CurrentOperation.Number1
  1482. ||CurrentOperation.Number2 >= Count
  1483. ){
  1484. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
  1485. ShellStatus = SHELL_INVALID_PARAMETER;
  1486. }
  1487. }
  1488. }
  1489. }
  1490. else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)CurrentParam, L"mod") == 0) {
  1491. if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) {
  1492. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
  1493. ShellStatus = SHELL_INVALID_PARAMETER;
  1494. } else {
  1495. CurrentOperation.Type = BcfgTypeMod;
  1496. CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
  1497. if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
  1498. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
  1499. ShellStatus = SHELL_INVALID_PARAMETER;
  1500. } else {
  1501. Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
  1502. CurrentOperation.Number1 = (UINT16)Intermediate;
  1503. if (CurrentOperation.Number1 >= Count) {
  1504. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
  1505. ShellStatus = SHELL_INVALID_PARAMETER;
  1506. } else {
  1507. ASSERT (CurrentOperation.Description == NULL);
  1508. CurrentOperation.Description = StrnCatGrow (&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
  1509. }
  1510. }
  1511. }
  1512. } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)CurrentParam, L"modf") == 0) {
  1513. if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) {
  1514. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
  1515. ShellStatus = SHELL_INVALID_PARAMETER;
  1516. } else {
  1517. CurrentOperation.Type = BcfgTypeModf;
  1518. CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
  1519. if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
  1520. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
  1521. ShellStatus = SHELL_INVALID_PARAMETER;
  1522. } else {
  1523. Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
  1524. CurrentOperation.Number1 = (UINT16)Intermediate;
  1525. if (CurrentOperation.Number1 >= Count) {
  1526. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
  1527. ShellStatus = SHELL_INVALID_PARAMETER;
  1528. } else {
  1529. ASSERT (CurrentOperation.FileName == NULL);
  1530. CurrentOperation.FileName = StrnCatGrow (&CurrentOperation.FileName, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
  1531. }
  1532. }
  1533. }
  1534. } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)CurrentParam, L"modp") == 0) {
  1535. if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) {
  1536. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
  1537. ShellStatus = SHELL_INVALID_PARAMETER;
  1538. } else {
  1539. CurrentOperation.Type = BcfgTypeModp;
  1540. CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
  1541. if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
  1542. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
  1543. ShellStatus = SHELL_INVALID_PARAMETER;
  1544. } else {
  1545. Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
  1546. CurrentOperation.Number1 = (UINT16)Intermediate;
  1547. if (CurrentOperation.Number1 >= Count) {
  1548. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
  1549. ShellStatus = SHELL_INVALID_PARAMETER;
  1550. } else {
  1551. ASSERT (CurrentOperation.FileName == NULL);
  1552. CurrentOperation.FileName = StrnCatGrow (&CurrentOperation.FileName, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
  1553. }
  1554. }
  1555. }
  1556. } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)CurrentParam, L"modh") == 0) {
  1557. if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) {
  1558. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
  1559. ShellStatus = SHELL_INVALID_PARAMETER;
  1560. } else {
  1561. CurrentOperation.Type = BcfgTypeModh;
  1562. CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
  1563. if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
  1564. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
  1565. ShellStatus = SHELL_INVALID_PARAMETER;
  1566. }
  1567. else {
  1568. Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
  1569. CurrentOperation.Number1 = (UINT16)Intermediate;
  1570. if (CurrentOperation.Number1 >= Count) {
  1571. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
  1572. ShellStatus = SHELL_INVALID_PARAMETER;
  1573. } else {
  1574. CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
  1575. if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
  1576. ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
  1577. ShellStatus = SHELL_INVALID_PARAMETER;
  1578. } else {
  1579. Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
  1580. CurrentOperation.HandleIndex = (UINT16)Intermediate;
  1581. }
  1582. }
  1583. }
  1584. }
  1585. } else {
  1586. ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
  1587. ShellStatus = SHELL_INVALID_PARAMETER;
  1588. }
  1589. }
  1590. }
  1591. if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax && CurrentOperation.Type < BcfgTypeMax) {
  1592. //
  1593. // we have all the info. Do the work
  1594. //
  1595. switch (CurrentOperation.Type) {
  1596. case BcfgTypeDump:
  1597. ShellStatus = BcfgDisplayDump(
  1598. CurrentOperation.Target == BcfgTargetBootOrder?L"Boot":L"Driver",
  1599. Count,
  1600. CurrentOperation.Order,
  1601. ShellCommandLineGetFlag(Package, L"-v"));
  1602. break;
  1603. case BcfgTypeMv:
  1604. ShellStatus = BcfgMove(
  1605. CurrentOperation.Target,
  1606. CurrentOperation.Order,
  1607. Count,
  1608. CurrentOperation.Number1,
  1609. CurrentOperation.Number2);
  1610. break;
  1611. case BcfgTypeRm:
  1612. ShellStatus = BcfgRemove(
  1613. CurrentOperation.Target,
  1614. CurrentOperation.Order,
  1615. Count,
  1616. CurrentOperation.Number1);
  1617. break;
  1618. case BcfgTypeAdd:
  1619. case BcfgTypeAddp:
  1620. case BcfgTypeAddh:
  1621. ShellStatus = BcfgAdd(
  1622. CurrentOperation.Number1,
  1623. CurrentOperation.FileName,
  1624. CurrentOperation.Description==NULL?L"":CurrentOperation.Description,
  1625. CurrentOperation.Order,
  1626. Count,
  1627. CurrentOperation.Target,
  1628. (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddh),
  1629. (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddp),
  1630. CurrentOperation.HandleIndex);
  1631. break;
  1632. case BcfgTypeMod:
  1633. case BcfgTypeModf:
  1634. case BcfgTypeModp:
  1635. case BcfgTypeModh:
  1636. ShellStatus = BcfgMod (&CurrentOperation, Count);
  1637. break;
  1638. case BcfgTypeOpt:
  1639. ShellStatus = BcfgAddOpt(
  1640. CurrentOperation.OptData,
  1641. CurrentOperation.Order,
  1642. Count,
  1643. CurrentOperation.Target);
  1644. break;
  1645. default:
  1646. ASSERT(FALSE);
  1647. }
  1648. }
  1649. }
  1650. if (Package != NULL) {
  1651. ShellCommandLineFreeVarList (Package);
  1652. }
  1653. if (CurrentOperation.FileName != NULL) {
  1654. FreePool(CurrentOperation.FileName);
  1655. }
  1656. if (CurrentOperation.Description != NULL) {
  1657. FreePool(CurrentOperation.Description);
  1658. }
  1659. if (CurrentOperation.Order != NULL) {
  1660. FreePool(CurrentOperation.Order);
  1661. }
  1662. return (ShellStatus);
  1663. }
  1664. /**
  1665. Function to get the filename with help context if HII will not be used.
  1666. @return The filename with help text in it.
  1667. **/
  1668. CONST CHAR16*
  1669. EFIAPI
  1670. ShellCommandGetManFileNameBcfg (
  1671. VOID
  1672. )
  1673. {
  1674. return (mFileName);
  1675. }
  1676. /**
  1677. "Constructor" for the library.
  1678. This will register the handler for the bcfg command.
  1679. @param[in] ImageHandle the image handle of the process
  1680. @param[in] SystemTable the EFI System Table pointer
  1681. @param[in] Name the profile name to use
  1682. @retval EFI_SUCCESS the shell command handlers were installed sucessfully
  1683. @retval EFI_UNSUPPORTED the shell level required was not found.
  1684. **/
  1685. EFI_STATUS
  1686. EFIAPI
  1687. BcfgLibraryRegisterBcfgCommand (
  1688. IN EFI_HANDLE ImageHandle,
  1689. IN EFI_SYSTEM_TABLE *SystemTable,
  1690. IN CONST CHAR16 *Name
  1691. )
  1692. {
  1693. if (gShellBcfgHiiHandle != NULL) {
  1694. return (EFI_SUCCESS);
  1695. }
  1696. gShellBcfgHiiHandle = HiiAddPackages (&gShellBcfgHiiGuid, gImageHandle, UefiShellBcfgCommandLibStrings, NULL);
  1697. if (gShellBcfgHiiHandle == NULL) {
  1698. return (EFI_DEVICE_ERROR);
  1699. }
  1700. //
  1701. // install our shell command handler
  1702. //
  1703. ShellCommandRegisterCommandName(L"bcfg", ShellCommandRunBcfg , ShellCommandGetManFileNameBcfg, 0, Name, FALSE, gShellBcfgHiiHandle, STRING_TOKEN(STR_GET_HELP_BCFG));
  1704. return (EFI_SUCCESS);
  1705. }
  1706. /**
  1707. Destructor for the library. free any resources.
  1708. @param ImageHandle The image handle of the process.
  1709. @param SystemTable The EFI System Table pointer.
  1710. **/
  1711. EFI_STATUS
  1712. EFIAPI
  1713. BcfgLibraryUnregisterBcfgCommand (
  1714. IN EFI_HANDLE ImageHandle,
  1715. IN EFI_SYSTEM_TABLE *SystemTable
  1716. )
  1717. {
  1718. if (gShellBcfgHiiHandle != NULL) {
  1719. HiiRemovePackages(gShellBcfgHiiHandle);
  1720. }
  1721. gShellBcfgHiiHandle = NULL;
  1722. return (EFI_SUCCESS);
  1723. }