Windows NT 4.0 source code leak
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.

664 lines
15 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1991-1993 Microsoft Corporation
  3. Module Name:
  4. jxenvirv.c
  5. Abstract:
  6. This module implements the HAL get and set environment variable routines
  7. for a MIPS system.
  8. Author:
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include "halp.h"
  14. #include "arccodes.h"
  15. #include "jazznvr.h"
  16. #include "string.h"
  17. //
  18. // Define local upcase macro.
  19. //
  20. #define UpCase(c) ((c) >= 'a' && (c) <= 'z' ? (c) - ('a' - 'A') : (c))
  21. KIRQL
  22. HalpMapNvram (
  23. VOID
  24. )
  25. /*++
  26. Routine Description:
  27. This function is called to map the NVRAM into a wired TB entry.
  28. Arguments:
  29. None.
  30. Return Value:
  31. The previous IRQL is returned as the function value.
  32. --*/
  33. {
  34. KIRQL OldIrql;
  35. ENTRYLO NvramPte[2];
  36. //
  37. // Construct a pair of PTE's to map NVRAM.
  38. //
  39. NvramPte[0].X1 = 0;
  40. NvramPte[0].PFN = NVRAM_PHYSICAL_BASE >> PAGE_SHIFT;
  41. NvramPte[0].G = 0;
  42. NvramPte[0].V = 1;
  43. NvramPte[0].D = 1;
  44. NvramPte[0].C = UNCACHED_POLICY;
  45. NvramPte[1] = NvramPte[0];
  46. NvramPte[1].PFN += 1;
  47. //
  48. // Raise IRQL to the highest level, allocate a TB entry, map NVRAM
  49. // using the alocated entry, and return the previous IRQL.
  50. //
  51. KeRaiseIrql(HIGH_LEVEL, &OldIrql);
  52. KeFillFixedEntryTb((PHARDWARE_PTE)&NvramPte[0],
  53. (PVOID)NVRAM_VIRTUAL_BASE,
  54. HalpAllocateTbEntry());
  55. return OldIrql;
  56. }
  57. VOID
  58. HalpUnmapNvram (
  59. IN KIRQL OldIrql
  60. )
  61. /*++
  62. Routine Description:
  63. This function is called to unmap the NVRAM from a wired entry in
  64. the TB.
  65. Arguments:
  66. OldIrql - Supplies the previous IRQL value.
  67. Return Value:
  68. None.
  69. --*/
  70. {
  71. //
  72. // Free the wired TB entry that was allocated to map NVRAM and lower
  73. // IRQL to its previous level.
  74. //
  75. HalpFreeTbEntry();
  76. KeLowerIrql(OldIrql);
  77. return;
  78. }
  79. ARC_STATUS
  80. HalpEnvironmentCheckChecksum (
  81. VOID
  82. )
  83. /*++
  84. Routine Description:
  85. This routine checks the NVRAM environment area checksum.
  86. N.B. The NVRAM must be mapped before this routine is called.
  87. Arguments:
  88. None.
  89. Return Value:
  90. ESUCCESS is returned if the checksum matches. Otherwise, EIO is returned.
  91. --*/
  92. {
  93. ULONG Checksum1;
  94. ULONG Checksum2;
  95. PUCHAR Environment;
  96. ULONG Index;
  97. PNV_CONFIGURATION NvConfiguration;
  98. //
  99. // Compute the NVRAM environment area checksum.
  100. //
  101. NvConfiguration = (PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE;
  102. Environment = &NvConfiguration->Environment[0];
  103. Checksum1 = 0;
  104. for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) {
  105. Checksum1 += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]);
  106. }
  107. //
  108. // Merge the checksum bytes from the NVRAM and compare to computed value.
  109. //
  110. Checksum2 = (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[0]) |
  111. (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[1]) << 8 |
  112. (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[2]) << 16 |
  113. (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[3]) << 24;
  114. //
  115. // If the checksum mismatches, then return an I/O error. Otherwise,
  116. // return a success status.
  117. //
  118. if (Checksum1 != Checksum2) {
  119. return EIO;
  120. } else {
  121. return ESUCCESS;
  122. }
  123. }
  124. VOID
  125. HalpEnvironmentSetChecksum (
  126. VOID
  127. )
  128. /*++
  129. Routine Description:
  130. This routine sets the NVRAM environment area checksum.
  131. N.B. The NVRAM must be mapped before this routine is called.
  132. Arguments:
  133. None.
  134. Return Value:
  135. None.
  136. --*/
  137. {
  138. ULONG Checksum;
  139. PUCHAR Environment;
  140. ULONG Index;
  141. PNV_CONFIGURATION NvConfiguration;
  142. //
  143. // Compute the NVRAM environment area checksum.
  144. //
  145. NvConfiguration = (PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE;
  146. Environment = &NvConfiguration->Environment[0];
  147. Checksum = 0;
  148. for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) {
  149. Checksum += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]);
  150. }
  151. //
  152. // Write the NVRAM environment area checksum.
  153. //
  154. WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[0],
  155. (UCHAR)(Checksum & 0xFF));
  156. WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[1],
  157. (UCHAR)((Checksum >> 8) & 0xFF));
  158. WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[2],
  159. (UCHAR)((Checksum >> 16) & 0xFF));
  160. WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[3],
  161. (UCHAR)(Checksum >> 24));
  162. return;
  163. }
  164. ARC_STATUS
  165. HalpFindEnvironmentVariable (
  166. IN PCHAR Variable,
  167. OUT PULONG VariableIndex,
  168. OUT PULONG ValueIndex
  169. )
  170. /*++
  171. Routine Description:
  172. This routine performs a case insensitive search of the NVRAM environment
  173. area for the specified variable name.
  174. N.B. The NVRAM must be mapped before this routine is called.
  175. Arguments:
  176. Variable - Supplies a pointer to a zero terminated string containing an
  177. environment variable name.
  178. Return Value:
  179. ESUCCESS is returned if the specified variable name is located. Otherwise,
  180. ENOENT is returned.
  181. --*/
  182. {
  183. PUCHAR Environment;
  184. ULONG Index;
  185. PUCHAR Name;
  186. //
  187. // If the variable name is null, then return no entry found.
  188. //
  189. if (*Variable == 0) {
  190. return ENOENT;
  191. }
  192. //
  193. // Search the environment section of the NVRAM for a variable name match.
  194. //
  195. Environment = &((PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE)->Environment[0];
  196. Index = 0;
  197. do {
  198. //
  199. // Set name to the beginning of the variable name and record the
  200. // current index value.
  201. //
  202. Name = Variable;
  203. *VariableIndex = Index;
  204. //
  205. // Search until the end of the current environment variable, the
  206. // end of the specified variable name, or the end of the NVRAM is
  207. // reached.
  208. //
  209. while ((Index < LENGTH_OF_ENVIRONMENT) &&
  210. (READ_REGISTER_UCHAR(&Environment[Index]) != 0) && (*Name != 0)) {
  211. if (READ_REGISTER_UCHAR(&Environment[Index]) != UpCase(*Name)) {
  212. break;
  213. }
  214. Name += 1;
  215. Index += 1;
  216. }
  217. //
  218. // Check for a match which is signified by the end of the variable
  219. // name and the equal separator in the current environment variable.
  220. //
  221. if ((*Name == 0) && (READ_REGISTER_UCHAR(&Environment[Index]) == '=')) {
  222. *ValueIndex = Index + 1;
  223. return ESUCCESS;
  224. }
  225. //
  226. // Advance to the start of the next variable.
  227. //
  228. while ((Index < LENGTH_OF_ENVIRONMENT) &&
  229. (READ_REGISTER_UCHAR(&Environment[Index]) != 0)) {
  230. Index += 1;
  231. }
  232. Index += 1;
  233. } while (Index < LENGTH_OF_ENVIRONMENT);
  234. return ENOENT;
  235. }
  236. ARC_STATUS
  237. HalGetEnvironmentVariable (
  238. IN PCHAR Variable,
  239. IN USHORT Length,
  240. OUT PCHAR Buffer
  241. )
  242. /*++
  243. Routine Description:
  244. This function locates an environment variable and returns its value.
  245. Arguments:
  246. Variable - Supplies a pointer to a zero terminated environment variable
  247. name.
  248. Length - Supplies the length of the value buffer in bytes.
  249. Buffer - Supplies a pointer to a buffer that receives the variable value.
  250. Return Value:
  251. ESUCCESS is returned if the enviroment variable is located. Otherwise,
  252. ENOENT is returned.
  253. --*/
  254. {
  255. PUCHAR Environment;
  256. ULONG Index;
  257. KIRQL OldIrql;
  258. ARC_STATUS Status;
  259. ULONG ValueIndex;
  260. ULONG VariableIndex;
  261. //
  262. // Map the NVRAM into the address space of the current process.
  263. //
  264. OldIrql = HalpMapNvram();
  265. //
  266. // If the checksum does not match or the specified variable cannot
  267. // be located, then set the status to no entry found. Otherwise, copy
  268. // the respective variable value to the specified output buffer.
  269. //
  270. Environment = &((PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE)->Environment[0];
  271. if ((HalpEnvironmentCheckChecksum() != ESUCCESS) ||
  272. (HalpFindEnvironmentVariable(Variable,
  273. &VariableIndex,
  274. &ValueIndex) != ESUCCESS)) {
  275. Status = ENOENT;
  276. } else {
  277. //
  278. // Copy the specified value to the output buffer.
  279. //
  280. for (Index = 0; Index < Length; Index += 1) {
  281. *Buffer = READ_REGISTER_UCHAR(&Environment[ValueIndex]);
  282. if (*Buffer == 0) {
  283. break;
  284. }
  285. Buffer += 1;
  286. ValueIndex += 1;
  287. }
  288. //
  289. // If the length terminated the loop, then return not enough memory.
  290. // Otherwise, return success.
  291. //
  292. if (Index == Length) {
  293. Status = ENOMEM;
  294. } else {
  295. Status = ESUCCESS;
  296. }
  297. }
  298. //
  299. // Unmap the NVRAM from the address space of the current process and
  300. // return the function status.
  301. //
  302. HalpUnmapNvram(OldIrql);
  303. return Status;
  304. }
  305. ARC_STATUS
  306. HalSetEnvironmentVariable (
  307. IN PCHAR Variable,
  308. IN PCHAR Value
  309. )
  310. /*++
  311. Routine Description:
  312. This function creates an environment variable with the specified value.
  313. Arguments:
  314. Variable - Supplies a pointer to an environment variable name.
  315. Value - Supplies a pointer to the environment variable value.
  316. Return Value:
  317. ESUCCESS is returned if the environment variable is created. Otherwise,
  318. ENOMEM is returned.
  319. --*/
  320. {
  321. UCHAR Character;
  322. PUCHAR Environment;
  323. KIRQL OldIrql;
  324. ARC_STATUS Status;
  325. ULONG TopIndex;
  326. ULONG VariableIndex;
  327. ULONG VariableLength;
  328. ULONG ValueEnd;
  329. ULONG ValueIndex;
  330. ULONG ValueLength;
  331. //
  332. // Map the NVRAM into the address space of the current process.
  333. //
  334. OldIrql = HalpMapNvram();
  335. Environment = &((PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE)->Environment[0];
  336. //
  337. // If the checksum does not match, then set status to an I/O error.
  338. //
  339. if (HalpEnvironmentCheckChecksum() != ESUCCESS) {
  340. Status = EIO;
  341. goto Unmap;
  342. }
  343. //
  344. // Determine the top of the environment area by scanning backwards until
  345. // the a non-null character is found or the beginning of the environment
  346. // area is reached.
  347. //
  348. for (TopIndex = (LENGTH_OF_ENVIRONMENT - 1); TopIndex > 0; TopIndex -= 1) {
  349. if (READ_REGISTER_UCHAR(&Environment[TopIndex]) != '\0') {
  350. break;
  351. }
  352. }
  353. //
  354. // If the environment area contains any data, then adjust the top index
  355. // to the first free byte.
  356. //
  357. if (TopIndex != 0) {
  358. TopIndex += 2;
  359. }
  360. //
  361. // Compute the length of the variable name and the variable value.
  362. //
  363. VariableLength = strlen(Variable) + 1;
  364. ValueLength = strlen(Value) + 1;
  365. //
  366. // Check to determine if the specified variable is currently defined.
  367. //
  368. if (HalpFindEnvironmentVariable(Variable,
  369. &VariableIndex,
  370. &ValueIndex) == ESUCCESS) {
  371. //
  372. // The specified variable is currently defined. Determine the end
  373. // of the variable value by scanning forward to the zero termination
  374. // byte.
  375. //
  376. ValueEnd = ValueIndex;
  377. while (READ_REGISTER_UCHAR(&Environment[ValueEnd]) != '\0') {
  378. ValueEnd += 1;
  379. }
  380. ValueEnd += 1;
  381. //
  382. // If there is enough free space for the new variable value, then
  383. // remove the current variable name and value from the environment
  384. // area, insert the new variable value at the end of the environment
  385. // if it is not null, and set the status to success. Otherwise, set
  386. // the status to no space available.
  387. //
  388. if ((ValueEnd - ValueIndex + LENGTH_OF_ENVIRONMENT - TopIndex) >= ValueLength) {
  389. while (ValueEnd != TopIndex) {
  390. Character = READ_REGISTER_UCHAR(&Environment[ValueEnd]);
  391. WRITE_REGISTER_UCHAR(&Environment[VariableIndex], Character);
  392. ValueEnd += 1;
  393. VariableIndex += 1;
  394. }
  395. ValueIndex = VariableIndex;
  396. while (ValueIndex != TopIndex) {
  397. WRITE_REGISTER_UCHAR(&Environment[ValueIndex], '\0');
  398. ValueIndex += 1;
  399. }
  400. //
  401. // If the new variable value is not null, then copy the variable
  402. // name and the variable value into the enviroment area.
  403. //
  404. if (*Value != '\0') {
  405. //
  406. // copy the variable name to the environment area.
  407. //
  408. do {
  409. WRITE_REGISTER_UCHAR(&Environment[VariableIndex], UpCase(*Variable));
  410. VariableIndex += 1;
  411. Variable += 1;
  412. } while (*Variable != '\0');
  413. //
  414. // Insert separator character and copy variable value to the
  415. // environment area.
  416. //
  417. WRITE_REGISTER_UCHAR(&Environment[VariableIndex], '=');
  418. VariableIndex += 1;
  419. do {
  420. WRITE_REGISTER_UCHAR(&Environment[VariableIndex], *Value);
  421. VariableIndex += 1;
  422. Value += 1;
  423. } while (*Value != '\0');
  424. }
  425. Status = ESUCCESS;
  426. } else {
  427. Status = ENOSPC;
  428. }
  429. } else {
  430. //
  431. // The specified variable does not currently have a value. If the
  432. // specified variable is null or has no value, then set the status
  433. // to success. Otherwise, if the free area is not large enough to
  434. // hold the new variable name and its value, then set the status to
  435. // no space available. Otherwise, insert the variable name and value
  436. // at the end of the environment area and set the status to success.
  437. //
  438. if ((*Variable == '\0') || (*Value == '\0')) {
  439. Status = ESUCCESS;
  440. } else if ((LENGTH_OF_ENVIRONMENT - TopIndex) <
  441. (VariableLength + ValueLength)) {
  442. Status = ENOSPC;
  443. } else {
  444. //
  445. // copy the variable name to the environment area.
  446. //
  447. do {
  448. WRITE_REGISTER_UCHAR(&Environment[TopIndex], UpCase(*Variable));
  449. TopIndex += 1;
  450. Variable += 1;
  451. } while (*Variable != '\0');
  452. //
  453. // Insert separator character and copy variable value to the
  454. // environment area.
  455. //
  456. WRITE_REGISTER_UCHAR(&Environment[TopIndex], '=');
  457. TopIndex += 1;
  458. do {
  459. WRITE_REGISTER_UCHAR(&Environment[TopIndex], *Value);
  460. TopIndex += 1;
  461. Value += 1;
  462. } while (*Value != '\0');
  463. Status = ESUCCESS;
  464. }
  465. }
  466. //
  467. // Compute the new checksum and write to the environment area.
  468. //
  469. HalpEnvironmentSetChecksum();
  470. //
  471. // Unmap the NVRAM from the address space of the current process.
  472. //
  473. Unmap:
  474. HalpUnmapNvram(OldIrql);
  475. return Status;
  476. }