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.

879 lines
20 KiB

  1. /*++
  2. Copyright (c) 1998 Intel Corporation
  3. Module Name:
  4. map.c
  5. Abstract:
  6. Shell environment short device name mapping information management
  7. Revision History
  8. --*/
  9. #include "shelle.h"
  10. /*
  11. *
  12. */
  13. extern LIST_ENTRY SEnvMap;
  14. STATIC CHAR16 *SEnvCurDevice;
  15. /*
  16. *
  17. */
  18. VOID
  19. SEnvInitMap (
  20. VOID
  21. )
  22. {
  23. /*
  24. * The mapping data is read in from the variable init.
  25. */
  26. /*
  27. * Init the default map device
  28. */
  29. SEnvCurDevice = StrDuplicate(L"none");
  30. }
  31. CHAR16 *
  32. SEnvGetDefaultMapping (
  33. IN EFI_HANDLE ImageHandle
  34. )
  35. {
  36. EFI_LOADED_IMAGE *LoadedImage;
  37. EFI_STATUS Status;
  38. LIST_ENTRY *Head;
  39. LIST_ENTRY *Link;
  40. VARIABLE_ID *Var;
  41. EFI_HANDLE Handle;
  42. EFI_DEVICE_PATH *DevicePath;
  43. Status = BS->HandleProtocol (ImageHandle, &LoadedImageProtocol, (VOID*)&LoadedImage);
  44. if (EFI_ERROR(Status) || LoadedImage==NULL) {
  45. return NULL;
  46. }
  47. Head = &SEnvMap;
  48. for (Link=Head->Flink; Link != Head; Link=Link->Flink) {
  49. Var = CR(Link, VARIABLE_ID, Link, VARIABLE_SIGNATURE);
  50. DevicePath = (EFI_DEVICE_PATH *)Var->u.Str;
  51. Status = BS->LocateDevicePath(&DevicePathProtocol,&DevicePath,&Handle);
  52. if (!EFI_ERROR(Status) && Handle!=NULL) {
  53. if (LoadedImage->DeviceHandle == Handle) {
  54. return(Var->Name);
  55. }
  56. }
  57. }
  58. return NULL;
  59. }
  60. VOID
  61. SEnvDumpMapping(
  62. IN UINTN SLen,
  63. IN BOOLEAN Verbose,
  64. IN VARIABLE_ID *Var
  65. )
  66. {
  67. CHAR16 *p;
  68. EFI_DEVICE_PATH *DPath;
  69. EFI_STATUS Status;
  70. EFI_HANDLE DeviceHandle;
  71. p = DevicePathToStr ((EFI_DEVICE_PATH *) Var->u.Str);
  72. Print(L" %h-.*s : %s\n", SLen, Var->Name, p);
  73. if (Verbose) {
  74. /* lookup handle for this mapping */
  75. DPath = (EFI_DEVICE_PATH *) Var->u.Value;
  76. Status = BS->LocateDevicePath (&DevicePathProtocol, &DPath, &DeviceHandle);
  77. if (EFI_ERROR(Status)) {
  78. Print(L"%*s= Handle for this mapping not found\n", SLen+3);
  79. } else {
  80. Print(L"%*s= Handle", SLen + 3, L"");
  81. SEnvDHProt (FALSE, 0, DeviceHandle);
  82. }
  83. /* print current directory for this mapping */
  84. Print(L"%*s> %s\n\n", SLen+3, L"", Var->CurDir ? Var->CurDir : L"\\");
  85. }
  86. FreePool (p);
  87. }
  88. EFI_STATUS
  89. SEnvCmdMap (
  90. IN EFI_HANDLE ImageHandle,
  91. IN EFI_SYSTEM_TABLE *SystemTable
  92. )
  93. /* Code for internal "map" command */
  94. {
  95. LIST_ENTRY *Link, *Head;
  96. VARIABLE_ID *Var;
  97. VARIABLE_ID *Found;
  98. CHAR16 *Name;
  99. CHAR16 *Value;
  100. UINTN SLen, Len;
  101. UINTN Size, DataSize;
  102. BOOLEAN Delete, Verbose, Remap;
  103. EFI_STATUS Status;
  104. UINTN Index;
  105. CHAR16 *p;
  106. EFI_HANDLE Handle;
  107. EFI_DEVICE_PATH *DevicePath;
  108. BOOLEAN PageBreaks;
  109. UINTN TempColumn;
  110. UINTN ScreenCount;
  111. UINTN ScreenSize;
  112. CHAR16 ReturnStr[1];
  113. InitializeShellApplication (ImageHandle, SystemTable);
  114. Head = &SEnvMap;
  115. Name = NULL;
  116. Value = NULL;
  117. Delete = FALSE;
  118. Verbose = FALSE;
  119. Remap = FALSE;
  120. Status = EFI_SUCCESS;
  121. Found = NULL;
  122. /*
  123. * Crack arguments
  124. */
  125. PageBreaks = FALSE;
  126. for (Index = 1; Index < SI->Argc; Index += 1) {
  127. p = SI->Argv[Index];
  128. if (*p == '-') {
  129. switch (p[1]) {
  130. case 'd':
  131. case 'D':
  132. Delete = TRUE;
  133. break;
  134. case 'v':
  135. case 'V':
  136. Verbose = TRUE;
  137. break;
  138. case 'r':
  139. case 'R':
  140. Remap = TRUE;
  141. break;
  142. case 'b' :
  143. case 'B' :
  144. PageBreaks = TRUE;
  145. ST->ConOut->QueryMode (ST->ConOut, ST->ConOut->Mode->Mode, &TempColumn, &ScreenSize);
  146. ScreenCount = 0;
  147. break;
  148. default:
  149. Print (L"Map: Unkown flag %s\n", p);
  150. return EFI_INVALID_PARAMETER;
  151. }
  152. continue;
  153. }
  154. if (!Name) {
  155. Name = p;
  156. continue;
  157. }
  158. if (!Value) {
  159. Value = p;
  160. continue;
  161. }
  162. Print (L"Map: too many arguments\n");
  163. return EFI_INVALID_PARAMETER;
  164. }
  165. if (Delete && Value) {
  166. Print (L"Map: too many arguments\n");
  167. }
  168. /*
  169. * Process
  170. */
  171. if (Remap && !Value && !Delete) {
  172. AcquireLock (&SEnvLock);
  173. for (Link=Head->Flink; Link != Head;) {
  174. Var = CR(Link, VARIABLE_ID, Link, VARIABLE_SIGNATURE);
  175. Status = RT->SetVariable (Var->Name, &SEnvMapId, 0, 0, NULL);
  176. Link = Link->Flink;
  177. RemoveEntryList (&Var->Link);
  178. FreePool (Var);
  179. }
  180. ReleaseLock (&SEnvLock);
  181. Status = SEnvReloadDefaults (ImageHandle,SystemTable);
  182. Remap = FALSE;
  183. }
  184. if (Value || Verbose) {
  185. SEnvLoadHandleTable ();
  186. if (Verbose) {
  187. SEnvLoadHandleProtocolInfo (&DevicePathProtocol);
  188. }
  189. }
  190. AcquireLock (&SEnvLock);
  191. SLen = 0;
  192. for (Link=Head->Flink; Link != Head; Link=Link->Flink) {
  193. Var = CR(Link, VARIABLE_ID, Link, VARIABLE_SIGNATURE);
  194. Len = StrLen(Var->Name);
  195. if (Len > SLen) {
  196. SLen = Len;
  197. }
  198. }
  199. if (!Name) {
  200. Print (L"%EDevice mapping table%N\n");
  201. for (Link=Head->Flink; Link != Head; Link=Link->Flink) {
  202. Var = CR(Link, VARIABLE_ID, Link, VARIABLE_SIGNATURE);
  203. SEnvDumpMapping(SLen, Verbose, Var);
  204. if (PageBreaks) {
  205. ScreenCount++;
  206. if (ScreenCount > ScreenSize - 4) {
  207. ScreenCount = 0;
  208. Print (L"\nPress Return to contiue :");
  209. Input (L"", ReturnStr, sizeof(ReturnStr)/sizeof(CHAR16));
  210. Print (L"\n\n");
  211. }
  212. }
  213. }
  214. } else {
  215. /*
  216. * Find the specified value
  217. */
  218. for (Link=Head->Flink; Link != Head; Link=Link->Flink) {
  219. Var = CR(Link, VARIABLE_ID, Link, VARIABLE_SIGNATURE);
  220. if (StriCmp(Var->Name, Name) == 0) {
  221. Found = Var;
  222. break;
  223. }
  224. }
  225. if (Found && Delete) {
  226. /*
  227. * Remove it from the store
  228. */
  229. Status = RT->SetVariable (Found->Name, &SEnvMapId, 0, 0, NULL);
  230. } else if (Value) {
  231. /*
  232. * Find the handle in question
  233. */
  234. Handle = SEnvHandleFromStr(Value);
  235. if (!Handle) {
  236. Print(L"map: Handle not found\n");
  237. Status = EFI_NOT_FOUND;
  238. goto Done;
  239. }
  240. /*
  241. * Get the handle's device path
  242. */
  243. DevicePath = DevicePathFromHandle(Handle);
  244. if (!DevicePath) {
  245. Print(L"map: handle does not have a device path\n");
  246. Status = EFI_INVALID_PARAMETER;
  247. goto Done;
  248. }
  249. DataSize = DevicePathSize(DevicePath);
  250. /*
  251. * Add it to the store
  252. */
  253. Status = RT->SetVariable (
  254. Found ? Found->Name : Name,
  255. &SEnvMapId,
  256. EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
  257. DataSize,
  258. DevicePath
  259. );
  260. if (!EFI_ERROR(Status)) {
  261. /*
  262. * Make a new in memory copy
  263. */
  264. Size = sizeof(VARIABLE_ID) + StrSize(Name) + DataSize;
  265. Var = AllocateZeroPool (Size);
  266. Var->Signature = VARIABLE_SIGNATURE;
  267. Var->u.Value = ((UINT8 *) Var) + sizeof(VARIABLE_ID);
  268. Var->Name = (CHAR16*) (Var->u.Value + DataSize);
  269. Var->ValueSize = DataSize;
  270. CopyMem (Var->u.Value, DevicePath, DataSize);
  271. StrCpy (Var->Name, Found ? Found->Name : Name);
  272. InsertTailList (Head, &Var->Link);
  273. }
  274. } else {
  275. if (Found) {
  276. SEnvDumpMapping(SLen, Verbose, Var);
  277. } else {
  278. Print(L"map: '%es' not found\n", Name);
  279. }
  280. Found = NULL;
  281. }
  282. /*
  283. * Remove the old in memory copy if there was one
  284. */
  285. if (Found) {
  286. RemoveEntryList (&Found->Link);
  287. FreePool (Found);
  288. }
  289. }
  290. Done:
  291. ReleaseLock (&SEnvLock);
  292. SEnvFreeHandleTable ();
  293. return Status;
  294. }
  295. VARIABLE_ID *
  296. SEnvMapDeviceFromName (
  297. IN OUT CHAR16 **pPath
  298. )
  299. /* Check the Path for a device name, and updates the path to point after
  300. * the device name. If no device name is found, the current default is used. */
  301. {
  302. CHAR16 *Path, *p;
  303. CHAR16 *MappedName, c;
  304. VARIABLE_ID *Var;
  305. LIST_ENTRY *Link;
  306. ASSERT_LOCKED (&SEnvLock);
  307. Var = NULL;
  308. Path = *pPath;
  309. /*
  310. * Check for a device name terminator
  311. */
  312. for(p = Path; *p && *p != ':' && *p != '\\'; p++) ;
  313. /*
  314. * Use either the passed in name or the current device name setting
  315. */
  316. MappedName = *p == ':' ? Path : SEnvCurDevice;
  317. /*
  318. * Null terminate the string in Path just in case that is the one we
  319. * are using
  320. */
  321. c = *p;
  322. *p = 0;
  323. /*
  324. * Find the mapping for the device
  325. */
  326. for (Link=SEnvMap.Flink; Link != &SEnvMap; Link=Link->Flink) {
  327. Var = CR(Link, VARIABLE_ID, Link, VARIABLE_SIGNATURE);
  328. if (StriCmp(Var->Name, MappedName) == 0) {
  329. break;
  330. }
  331. }
  332. /*
  333. * Restore the path
  334. */
  335. *p = c;
  336. /*
  337. * If the mapped device was not found, return NULL
  338. */
  339. if (Link == &SEnvMap) {
  340. DEBUG((D_PARSE, "SEnvNameToPath: Mapping for '%es' not found\n", Path));
  341. return NULL;
  342. }
  343. /*
  344. * If we found it as part of the path, skip the path over it
  345. */
  346. if (MappedName == Path) {
  347. *pPath = p + 1;
  348. }
  349. /*
  350. * Return the target mapping
  351. */
  352. return Var;
  353. }
  354. EFI_DEVICE_PATH *
  355. SEnvIFileNameToPath (
  356. IN CHAR16 *Path
  357. )
  358. /* Builds a device path from the filename string. Note that the
  359. * device name must already be stripped off of the file name string */
  360. {
  361. CHAR16 *LPath, *ps;
  362. BOOLEAN UseLPath;
  363. EFI_DEVICE_PATH *DPath, *Node, *NewPath;
  364. CHAR16 Buffer[MAX_ARG_LENGTH];
  365. UINTN Index;
  366. ASSERT_LOCKED (&SEnvLock);
  367. DPath = NULL;
  368. /*
  369. * If no path, return the root
  370. */
  371. if (!*Path) {
  372. DPath = FileDevicePath(NULL, L"\\");
  373. }
  374. /*
  375. * Build a file path for the name component(s)
  376. */
  377. while (*Path) {
  378. Index = 0;
  379. LPath = NULL;
  380. UseLPath = FALSE;
  381. ps = Path;
  382. while (*ps) {
  383. /* if buffer has run out, just handle to LPath */
  384. if (Index > MAX_ARG_LENGTH-2 || *ps == '#') {
  385. UseLPath = TRUE;
  386. break;
  387. }
  388. if (*ps == '^') {
  389. if (ps[1]) {
  390. ps += 1;
  391. Buffer[Index++] = *ps;
  392. }
  393. ps += 1;
  394. continue;
  395. }
  396. if (*ps == '\\') {
  397. LPath = ps;
  398. }
  399. Buffer[Index++] = *ps;
  400. ps += 1;
  401. }
  402. if (UseLPath) {
  403. Index = LPath ? LPath - Path : 0;
  404. ps = Path + Index;
  405. }
  406. /*
  407. * If we have part of a path name, append it to the device path
  408. */
  409. if (Index) {
  410. Buffer[Index] = 0;
  411. Node = FileDevicePath(NULL, Buffer);
  412. NewPath = AppendDevicePath (DPath, Node);
  413. FreePool (Node);
  414. if (DPath) {
  415. FreePool (DPath);
  416. }
  417. DPath = NewPath;
  418. }
  419. if (*ps == 0) {
  420. break;
  421. }
  422. Path = ps + 1;
  423. }
  424. return DPath;
  425. }
  426. EFI_DEVICE_PATH *
  427. SEnvFileNameToPath (
  428. IN CHAR16 *Path
  429. )
  430. {
  431. EFI_DEVICE_PATH *FilePath;
  432. AcquireLock (&SEnvLock);
  433. FilePath = SEnvIFileNameToPath (Path);
  434. ReleaseLock (&SEnvLock);
  435. return FilePath;
  436. }
  437. EFI_DEVICE_PATH *
  438. SEnvINameToPath (
  439. IN CHAR16 *Path
  440. )
  441. /* Convert a filesystem stlye name to an file path */
  442. {
  443. EFI_DEVICE_PATH *DPath, *FPath, *RPath, *FilePath;
  444. VARIABLE_ID *Var;
  445. BOOLEAN FreeDPath;
  446. DPath = NULL;
  447. RPath = NULL;
  448. FPath = NULL;
  449. FilePath = NULL;
  450. FreeDPath = FALSE;
  451. ASSERT_LOCKED (&SEnvLock);
  452. /*
  453. * Get the device for the name, and advance past the device name
  454. */
  455. Var = SEnvMapDeviceFromName (&Path);
  456. if (!Var) {
  457. DEBUG((D_PARSE, "SEnvNameToPath: mapped device not found\n"));
  458. goto Done;
  459. }
  460. /*
  461. * Start the file path with this mapping
  462. */
  463. DPath = (EFI_DEVICE_PATH *) Var->u.Value;
  464. /*
  465. * If the path is realitve, append the current dir of the device to the dpath
  466. */
  467. if (*Path != '\\') {
  468. RPath = SEnvIFileNameToPath (Var->CurDir ? Var->CurDir : L"\\");
  469. DPath = AppendDevicePath (DPath, RPath);
  470. FreeDPath = TRUE;
  471. }
  472. /*
  473. * Build a file path for the rest of the name string
  474. */
  475. FPath = SEnvIFileNameToPath (Path);
  476. /*
  477. * Append the 2 paths
  478. */
  479. FilePath = AppendDevicePath(DPath, FPath);
  480. /*
  481. * Done
  482. */
  483. Done:
  484. if (DPath && FreeDPath) {
  485. FreePool (DPath);
  486. }
  487. if (RPath) {
  488. FreePool (RPath);
  489. }
  490. if (FPath) {
  491. FreePool (FPath);
  492. }
  493. return FilePath;
  494. }
  495. EFI_DEVICE_PATH *
  496. SEnvNameToPath (
  497. IN CHAR16 *Path
  498. )
  499. {
  500. EFI_DEVICE_PATH *DPath;
  501. AcquireLock (&SEnvLock);
  502. DPath = SEnvINameToPath (Path);
  503. ReleaseLock (&SEnvLock);
  504. return DPath;
  505. }
  506. EFI_STATUS
  507. SEnvCmdCd (
  508. IN EFI_HANDLE ImageHandle,
  509. IN EFI_SYSTEM_TABLE *SystemTable
  510. )
  511. {
  512. EFI_DEVICE_PATH *FilePath;
  513. EFI_STATUS Status;
  514. EFI_FILE_HANDLE OpenDir;
  515. CHAR16 *Dir;
  516. CHAR16 *CurDir;
  517. VARIABLE_ID *Var;
  518. EFI_FILE_INFO *FileInfo;
  519. InitializeShellApplication (ImageHandle, SystemTable);
  520. FilePath = NULL;
  521. /*
  522. * If no arguments, print the current directory
  523. */
  524. if (SI->Argc == 1) {
  525. Dir = SEnvGetCurDir(NULL);
  526. if (Dir) {
  527. Print (L"%s\n", Dir);
  528. FreePool (Dir);
  529. } else {
  530. Print (L"no current directory\n");
  531. }
  532. return EFI_SUCCESS;
  533. }
  534. AcquireLock (&SEnvLock);
  535. /*
  536. * If more then 1 argument, syntax
  537. */
  538. if (SI->Argc > 2) {
  539. Print (L"cd: too many arguments\n");
  540. Status =EFI_INVALID_PARAMETER;
  541. goto Done;
  542. }
  543. /*
  544. * Find the target device
  545. */
  546. Dir = SI->Argv[1];
  547. Var = SEnvMapDeviceFromName (&Dir);
  548. if (!Var) {
  549. Print(L"cd: mapped device not found\n");
  550. Status = EFI_NOT_FOUND;
  551. goto Done;
  552. }
  553. /*
  554. * If there's no path specified, print the current path for the device
  555. */
  556. if (*Dir == 0) {
  557. Print (L"%s\n", Var->CurDir ? Var->CurDir : L"\\");
  558. Status = EFI_SUCCESS;
  559. goto Done;
  560. }
  561. /*
  562. * Build a file path for the argument
  563. */
  564. FilePath = SEnvINameToPath (SI->Argv[1]);
  565. if (!FilePath) {
  566. Status = EFI_NOT_FOUND;
  567. goto Done;
  568. }
  569. /*
  570. * Open the target directory
  571. */
  572. OpenDir = ShellOpenFilePath(FilePath, EFI_FILE_MODE_READ);
  573. if (!OpenDir) {
  574. Print (L"cd: target directory not found\n");
  575. Status = EFI_NOT_FOUND;
  576. goto Done;
  577. }
  578. /*
  579. * Get information on the file path that was opened.
  580. */
  581. FileInfo = LibFileInfo(OpenDir);
  582. if (FileInfo == NULL) {
  583. Status = EFI_NOT_FOUND;
  584. goto Done;
  585. }
  586. /*
  587. * Verify that the file opened is a directory.
  588. */
  589. if (!(FileInfo->Attribute & EFI_FILE_DIRECTORY)) {
  590. Print (L"cd: target is not a directory\n");
  591. FreePool (FileInfo);
  592. OpenDir->Close (OpenDir);
  593. Status = EFI_NOT_FOUND;
  594. goto Done;
  595. }
  596. FreePool (FileInfo);
  597. CurDir = SEnvFileHandleToFileName(OpenDir);
  598. OpenDir->Close (OpenDir);
  599. /*
  600. * If we have a new path, update the device
  601. */
  602. if (CurDir) {
  603. if (Var->CurDir) {
  604. FreePool(Var->CurDir);
  605. }
  606. Var->CurDir = CurDir;
  607. } else {
  608. Print (L"cd: could not cd to '%hs%'\n", FilePath);
  609. }
  610. Status = EFI_SUCCESS;
  611. Done:
  612. ReleaseLock (&SEnvLock);
  613. if (FilePath) {
  614. FreePool (FilePath);
  615. }
  616. return Status;
  617. }
  618. CHAR16 *
  619. SEnvGetCurDir (
  620. IN CHAR16 *DeviceName OPTIONAL
  621. )
  622. /* N.B. results are allocated in pool */
  623. {
  624. CHAR16 *Dir;
  625. LIST_ENTRY *Link;
  626. VARIABLE_ID *Var;
  627. Dir = NULL;
  628. if (!DeviceName) {
  629. DeviceName = SEnvCurDevice;
  630. }
  631. AcquireLock (&SEnvLock);
  632. for (Link=SEnvMap.Flink; Link != &SEnvMap; Link=Link->Flink) {
  633. Var = CR(Link, VARIABLE_ID, Link, VARIABLE_SIGNATURE);
  634. if (StriCmp(Var->Name, DeviceName) == 0) {
  635. Dir = PoolPrint(L"%s:%s", Var->Name, Var->CurDir ? Var->CurDir : L"\\");
  636. break;
  637. }
  638. }
  639. ReleaseLock (&SEnvLock);
  640. return Dir;
  641. }
  642. EFI_STATUS
  643. SEnvSetCurrentDevice (
  644. IN CHAR16 *Name
  645. )
  646. {
  647. VARIABLE_ID *Var;
  648. LIST_ENTRY *Link;
  649. EFI_STATUS Status;
  650. UINTN Len;
  651. CHAR16 *NewName, c;
  652. Len = StrLen(Name);
  653. if (Len < 1) {
  654. return EFI_INVALID_PARAMETER;
  655. }
  656. /*
  657. * If the name ends with a ":" strip it off
  658. */
  659. Len -= 1;
  660. c = Name[Len];
  661. if (c == ':') {
  662. Name[Len] = 0;
  663. }
  664. Status = EFI_NO_MAPPING;
  665. AcquireLock (&SEnvLock);
  666. for (Link=SEnvMap.Flink; Link != &SEnvMap; Link=Link->Flink) {
  667. Var = CR(Link, VARIABLE_ID, Link, VARIABLE_SIGNATURE);
  668. if (StriCmp(Var->Name, Name) == 0) {
  669. NewName = StrDuplicate(Name);
  670. if (NewName) {
  671. FreePool (SEnvCurDevice);
  672. SEnvCurDevice = NewName;
  673. }
  674. Status = EFI_SUCCESS;
  675. break;
  676. }
  677. }
  678. ReleaseLock (&SEnvLock);
  679. /*
  680. * Restore the name
  681. */
  682. Name[Len] = c;
  683. return Status;
  684. }