]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellDebug1CommandsLib/Mm.c
Add "Debug1" profile (all but Edit and HexEdit commands)
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / Mm.c
1 /** @file
2 Main file for Mm shell Debug1 function.
3
4 Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "UefiShellDebug1CommandsLib.h"
16 #include <Library/ShellLib.h>
17 #include <Protocol/PciRootBridgeIo.h>
18 #include <Protocol/DeviceIo.h>
19
20 typedef enum {
21 EfiMemory,
22 EFIMemoryMappedIo,
23 EfiIo,
24 EfiPciConfig,
25 EfiPciEConfig
26 } EFI_ACCESS_TYPE;
27
28 EFI_STATUS
29 EFIAPI
30 DumpIoModify (
31 IN EFI_HANDLE ImageHandle,
32 IN EFI_SYSTEM_TABLE *SystemTable
33 );
34
35 VOID
36 EFIAPI
37 ReadMem (
38 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
39 IN UINT64 Address,
40 IN UINTN Size,
41 IN VOID *Buffer
42 );
43
44 VOID
45 EFIAPI
46 WriteMem (
47 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
48 IN UINT64 Address,
49 IN UINTN Size,
50 IN VOID *Buffer
51 );
52
53 BOOLEAN
54 EFIAPI
55 GetHex (
56 IN UINT16 *str,
57 OUT UINT64 *data
58 );
59
60 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
61 {L"-mmio", TypeFlag},
62 {L"-mem", TypeFlag},
63 {L"-io", TypeFlag},
64 {L"-pci", TypeFlag},
65 {L"-pcie", TypeFlag},
66 {L"-n", TypeFlag},
67 {L"-w", TypeValue},
68 {NULL, TypeMax}
69 };
70
71 STATIC CONST UINT64 MaxNum[9] = { 0xff, 0xffff, 0xffffffff, 0xffffffffffffffff };
72
73 /**
74 Get the PCI-E Address from a PCI address format 0x0000ssbbddffrrr
75 where ss is SEGMENT, bb is BUS, dd is DEVICE, ff is FUNCTION
76 and rrr is REGISTER (extension format for PCI-E).
77
78 @param[in] InputAddress PCI address format on input.
79 @param[out]PciEAddress PCI-E address extention format.
80 **/
81 VOID
82 EFIAPI
83 GetPciEAddressFromInputAddress (
84 IN UINT64 InputAddress,
85 OUT UINT64 *PciEAddress
86 )
87 {
88 *PciEAddress = RShiftU64(InputAddress & ~(UINT64) 0xFFF, 4);
89 *PciEAddress += LShiftU64((UINT16) InputAddress & 0x0FFF, 32);
90 }
91
92 /**
93 Function for 'mm' command.
94
95 @param[in] ImageHandle Handle to the Image (NULL if Internal).
96 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
97 **/
98 SHELL_STATUS
99 EFIAPI
100 ShellCommandRunMm (
101 IN EFI_HANDLE ImageHandle,
102 IN EFI_SYSTEM_TABLE *SystemTable
103 )
104 {
105 EFI_STATUS Status;
106 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev;
107 UINT64 Address;
108 UINT64 PciEAddress;
109 UINT64 Value;
110 UINT32 SegmentNumber;
111 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width;
112 EFI_ACCESS_TYPE AccessType;
113 UINT64 Buffer;
114 UINTN Index;
115 UINTN Size;
116 CHAR16 *AddressStr;
117 // CHAR16 *ValueStr;
118 BOOLEAN Complete;
119 CHAR16 *InputStr;
120 BOOLEAN Interactive;
121 EFI_HANDLE *HandleBuffer;
122 UINTN BufferSize;
123 UINTN ItemValue;
124 LIST_ENTRY *Package;
125 CHAR16 *ProblemParam;
126 SHELL_STATUS ShellStatus;
127 CONST CHAR16 *Temp;
128
129 Address = 0;
130 PciEAddress = 0;
131 IoDev = NULL;
132 HandleBuffer = NULL;
133 BufferSize = 0;
134 SegmentNumber = 0;
135 ShellStatus = SHELL_SUCCESS;
136 InputStr = NULL;
137
138 //
139 // Parse arguments
140 //
141 Width = EfiPciWidthUint8;
142 Size = 1;
143 AccessType = EfiMemory;
144 AddressStr = NULL;
145 // ValueStr = NULL;
146 Interactive = TRUE;
147 Package = NULL;
148
149 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
150 if (EFI_ERROR(Status)) {
151 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
152 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, ProblemParam);
153 FreePool(ProblemParam);
154 ShellStatus = SHELL_INVALID_PARAMETER;
155 goto Done;
156 } else {
157 ASSERT(FALSE);
158 }
159 } else {
160 if (ShellCommandLineGetCount(Package) < 1) {
161 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);
162 ShellStatus = SHELL_INVALID_PARAMETER;
163 goto Done;
164 } else if (ShellCommandLineGetCount(Package) > 3) {
165 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle);
166 ShellStatus = SHELL_INVALID_PARAMETER;
167 goto Done;
168 } else {
169 if (ShellCommandLineGetFlag(Package, L"-mmio")) {
170 AccessType = EFIMemoryMappedIo;
171 } else if (ShellCommandLineGetFlag(Package, L"-mem")) {
172 AccessType = EfiMemory;
173 } else if (ShellCommandLineGetFlag(Package, L"-io")) {
174 AccessType = EfiIo;
175 } else if (ShellCommandLineGetFlag(Package, L"-pci")) {
176 AccessType = EfiPciConfig;
177 } else if (ShellCommandLineGetFlag(Package, L"-pcie")) {
178 AccessType = EfiPciEConfig;
179 }
180 }
181
182 if (ShellCommandLineGetFlag (Package, L"-n")) {
183 Interactive = FALSE;
184 }
185
186 Temp = ShellCommandLineGetValue(Package, L"-w");
187 if (Temp != NULL) {
188 ItemValue = StrDecimalToUintn (Temp);
189
190 switch (ItemValue) {
191 case 1:
192 Width = EfiPciWidthUint8;
193 Size = 1;
194 break;
195
196 case 2:
197 Width = EfiPciWidthUint16;
198 Size = 2;
199 break;
200
201 case 4:
202 Width = EfiPciWidthUint32;
203 Size = 4;
204 break;
205
206 case 8:
207 Width = EfiPciWidthUint64;
208 Size = 8;
209 break;
210
211 default:
212 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"-w");
213 ShellStatus = SHELL_INVALID_PARAMETER;
214 goto Done;
215 }
216 }
217
218 Temp = ShellCommandLineGetRawValue(Package, 1);
219 if (Temp != NULL) {
220 Address = StrHexToUint64(Temp);
221 }
222
223 Temp = ShellCommandLineGetRawValue(Package, 2);
224 if (Temp != NULL) {
225 Value = StrHexToUint64(Temp);
226 switch (Size) {
227 case 1:
228 if (Value > 0xFF) {
229 ShellStatus = SHELL_INVALID_PARAMETER;
230 }
231 break;
232
233 case 2:
234 if (Value > 0xFFFF) {
235 ShellStatus = SHELL_INVALID_PARAMETER;
236 }
237 break;
238
239 case 4:
240 if (Value > 0xFFFFFFFF) {
241 ShellStatus = SHELL_INVALID_PARAMETER;
242 }
243 break;
244
245 default:
246 break;
247 }
248
249 if (ShellStatus != SHELL_SUCCESS) {
250 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, Temp);
251 ShellStatus = SHELL_INVALID_PARAMETER;
252 goto Done;
253 }
254 }
255
256 if ((Address & (Size - 1)) != 0) {
257 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_NOT_ALIGNED), gShellDebug1HiiHandle, Address);
258 ShellStatus = SHELL_INVALID_PARAMETER;
259 goto Done;
260 }
261 //
262 // locate DeviceIO protocol interface
263 //
264 if (AccessType != EfiMemory) {
265 Status = gBS->LocateHandleBuffer (
266 ByProtocol,
267 &gEfiPciRootBridgeIoProtocolGuid,
268 NULL,
269 &BufferSize,
270 &HandleBuffer
271 );
272 if (EFI_ERROR (Status)) {
273 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_NF), gShellDebug1HiiHandle);
274 ShellStatus = SHELL_NOT_FOUND;
275 goto Done;
276 }
277 //
278 // In the case of PCI or PCIE
279 // Get segment number and mask the segment bits in Address
280 //
281 if (AccessType == EfiPciEConfig) {
282 SegmentNumber = (UINT32) RShiftU64 (Address, 36) & 0xff;
283 Address &= 0xfffffffff;
284 } else {
285 if (AccessType == EfiPciConfig) {
286 SegmentNumber = (UINT32) RShiftU64 (Address, 32) & 0xff;
287 Address &= 0xffffffff;
288 }
289 }
290 //
291 // Find the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL of the specified segment number
292 //
293 for (Index = 0; Index < BufferSize; Index++) {
294 Status = gBS->HandleProtocol (
295 HandleBuffer[Index],
296 &gEfiPciRootBridgeIoProtocolGuid,
297 (VOID *) &IoDev
298 );
299 if (EFI_ERROR (Status)) {
300 continue;
301 }
302 if (IoDev->SegmentNumber != SegmentNumber) {
303 IoDev = NULL;
304 }
305 }
306 if (IoDev == NULL) {
307 // TODO add token
308 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_SEGMENT_NOT_FOUND), gShellDebug1HiiHandle, SegmentNumber);
309 ShellStatus = SHELL_INVALID_PARAMETER;
310 goto Done;
311 }
312 }
313
314 if (AccessType == EfiIo && Address + Size > 0x10000) {
315 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS_RANGE), gShellDebug1HiiHandle);
316 ShellStatus = SHELL_INVALID_PARAMETER;
317 goto Done;
318 }
319
320 if (AccessType == EfiPciEConfig) {
321 GetPciEAddressFromInputAddress (Address, &PciEAddress);
322 }
323
324 // //
325 // // Set value
326 // //
327 // if (ValueStr != NULL) {
328 // if (AccessType == EFIMemoryMappedIo) {
329 // IoDev->Mem.Write (IoDev, Width, Address, 1, &Value);
330 // } else if (AccessType == EfiIo) {
331 // IoDev->Io.Write (IoDev, Width, Address, 1, &Value);
332 // } else if (AccessType == EfiPciConfig) {
333 // IoDev->Pci.Write (IoDev, Width, Address, 1, &Value);
334 // } else if (AccessType == EfiPciEConfig) {
335 // IoDev->Pci.Write (IoDev, Width, PciEAddress, 1, &Buffer);
336 // } else {
337 // WriteMem (Width, Address, 1, &Value);
338 // }
339 //
340 // ASSERT(ShellStatus == SHELL_SUCCESS);
341 // goto Done;
342 // }
343
344
345 //
346 // non-interactive mode
347 //
348 if (!Interactive) {
349 Buffer = 0;
350 if (AccessType == EFIMemoryMappedIo) {
351 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MMIO), gShellDebug1HiiHandle);
352 IoDev->Mem.Read (IoDev, Width, Address, 1, &Buffer);
353 } else if (AccessType == EfiIo) {
354 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_IO), gShellDebug1HiiHandle);
355 IoDev->Io.Read (IoDev, Width, Address, 1, &Buffer);
356 } else if (AccessType == EfiPciConfig) {
357 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCI), gShellDebug1HiiHandle);
358 IoDev->Pci.Read (IoDev, Width, Address, 1, &Buffer);
359 } else if (AccessType == EfiPciEConfig) {
360 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCIE), gShellDebug1HiiHandle);
361 IoDev->Pci.Read (IoDev, Width, PciEAddress, 1, &Buffer);
362 } else {
363 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MEM), gShellDebug1HiiHandle);
364 ReadMem (Width, Address, 1, &Buffer);
365 }
366
367 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address);
368 if (Size == 1) {
369 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF2), gShellDebug1HiiHandle, Buffer);
370 } else if (Size == 2) {
371 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF4), gShellDebug1HiiHandle, Buffer);
372 } else if (Size == 4) {
373 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF8), gShellDebug1HiiHandle, Buffer);
374 } else if (Size == 8) {
375 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF16), gShellDebug1HiiHandle, Buffer);
376 }
377
378 ShellPrintEx(-1, -1, L"\r\n");
379
380 ASSERT(ShellStatus == SHELL_SUCCESS);
381 goto Done;
382 }
383 //
384 // interactive mode
385 //
386 Complete = FALSE;
387 do {
388 if (AccessType == EfiIo && Address + Size > 0x10000) {
389 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS_RANGE2), gShellDebug1HiiHandle);
390 // PrintToken (STRING_TOKEN (STR_IOMOD_IO_ADDRESS_2), HiiHandle, L"mm");
391 break;
392 }
393
394 Buffer = 0;
395 if (AccessType == EFIMemoryMappedIo) {
396 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MMIO), gShellDebug1HiiHandle);
397 // PrintToken (STRING_TOKEN (STR_IOMOD_HMMIO), HiiHandle);
398 IoDev->Mem.Read (IoDev, Width, Address, 1, &Buffer);
399 } else if (AccessType == EfiIo) {
400 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_IO), gShellDebug1HiiHandle);
401 // PrintToken (STRING_TOKEN (STR_IOMOD_HIO), HiiHandle);
402 IoDev->Io.Read (IoDev, Width, Address, 1, &Buffer);
403 } else if (AccessType == EfiPciConfig) {
404 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCI), gShellDebug1HiiHandle);
405 // PrintToken (STRING_TOKEN (STR_IOMOD_HPCI), HiiHandle);
406 IoDev->Pci.Read (IoDev, Width, Address, 1, &Buffer);
407 } else if (AccessType == EfiPciEConfig) {
408 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCIE), gShellDebug1HiiHandle);
409 // PrintToken (STRING_TOKEN (STR_IOMOD_HPCIE), HiiHandle);
410 IoDev->Pci.Read (IoDev, Width, PciEAddress, 1, &Buffer);
411 } else {
412 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MEM), gShellDebug1HiiHandle);
413 // PrintToken (STRING_TOKEN (STR_IOMOD_HMEM), HiiHandle);
414 ReadMem (Width, Address, 1, &Buffer);
415 }
416
417 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address);
418 // PrintToken (STRING_TOKEN (STR_IOMOD_ADDRESS), HiiHandle, Address);
419
420 if (Size == 1) {
421 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF2), gShellDebug1HiiHandle, Buffer);
422 // PrintToken (STRING_TOKEN (STR_IOMOD_BUFFER_2), HiiHandle, Buffer);
423 } else if (Size == 2) {
424 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF4), gShellDebug1HiiHandle, Buffer);
425 // PrintToken (STRING_TOKEN (STR_IOMOD_BUFFER_4), HiiHandle, Buffer);
426 } else if (Size == 4) {
427 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF8), gShellDebug1HiiHandle, Buffer);
428 // PrintToken (STRING_TOKEN (STR_IOMOD_BUFFER_8), HiiHandle, Buffer);
429 } else if (Size == 8) {
430 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF16), gShellDebug1HiiHandle, Buffer);
431 // PrintToken (STRING_TOKEN (STR_IOMOD_BUFFER_16), HiiHandle, Buffer);
432 }
433 //
434 // wait user input to modify
435 //
436 if (InputStr != NULL) {
437 FreePool(InputStr);
438 }
439 ShellPromptForResponse(ShellPromptResponseTypeFreeform, NULL, (VOID**)&InputStr);
440
441 //
442 // skip space characters
443 //
444 for (Index = 0; InputStr[Index] == ' '; Index++);
445
446 //
447 // parse input string
448 //
449 if (InputStr[Index] == '.' || InputStr[Index] == 'q' || InputStr[Index] == 'Q') {
450 Complete = TRUE;
451 } else if (InputStr[Index] == CHAR_NULL) {
452 //
453 // Continue to next address
454 //
455 } else if (GetHex (InputStr + Index, &Buffer) && Buffer <= MaxNum[Width]) {
456 if (AccessType == EFIMemoryMappedIo) {
457 IoDev->Mem.Write (IoDev, Width, Address, 1, &Buffer);
458 } else if (AccessType == EfiIo) {
459 IoDev->Io.Write (IoDev, Width, Address, 1, &Buffer);
460 } else if (AccessType == EfiPciConfig) {
461 IoDev->Pci.Write (IoDev, Width, Address, 1, &Buffer);
462 } else if (AccessType == EfiPciEConfig) {
463 IoDev->Pci.Write (IoDev, Width, PciEAddress, 1, &Buffer);
464 } else {
465 WriteMem (Width, Address, 1, &Buffer);
466 }
467 } else {
468 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ERROR), gShellDebug1HiiHandle);
469 // PrintToken (STRING_TOKEN (STR_IOMOD_ERROR), HiiHandle);
470 continue;
471 }
472
473 Address += Size;
474 if (AccessType == EfiPciEConfig) {
475 GetPciEAddressFromInputAddress (Address, &PciEAddress);
476 }
477 ShellPrintEx(-1, -1, L"\r\n");
478 // Print (L"\n");
479 } while (!Complete);
480 }
481 ASSERT(ShellStatus == SHELL_SUCCESS);
482 Done:
483
484 if (InputStr != NULL) {
485 FreePool(InputStr);
486 }
487 if (HandleBuffer != NULL) {
488 FreePool (HandleBuffer);
489 }
490 if (Package != NULL) {
491 ShellCommandLineFreeVarList (Package);
492 }
493 return ShellStatus;
494 }
495
496
497 VOID
498 EFIAPI
499 ReadMem (
500 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
501 IN UINT64 Address,
502 IN UINTN Size,
503 IN VOID *Buffer
504 )
505 {
506 do {
507 if (Width == EfiPciWidthUint8) {
508 *(UINT8 *) Buffer = *(UINT8 *) (UINTN) Address;
509 Address -= 1;
510 } else if (Width == EfiPciWidthUint16) {
511 *(UINT16 *) Buffer = *(UINT16 *) (UINTN) Address;
512 Address -= 2;
513 } else if (Width == EfiPciWidthUint32) {
514 *(UINT32 *) Buffer = *(UINT32 *) (UINTN) Address;
515 Address -= 4;
516 } else if (Width == EfiPciWidthUint64) {
517 *(UINT64 *) Buffer = *(UINT64 *) (UINTN) Address;
518 Address -= 8;
519 } else {
520 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_READ_ERROR), gShellDebug1HiiHandle);
521 // PrintToken (STRING_TOKEN (STR_IOMOD_READ_MEM_ERROR), HiiHandle);
522 break;
523 }
524 //
525 //
526 //
527 Size--;
528 } while (Size > 0);
529 }
530
531 VOID
532 EFIAPI
533 WriteMem (
534 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
535 IN UINT64 Address,
536 IN UINTN Size,
537 IN VOID *Buffer
538 )
539 {
540 do {
541 if (Width == EfiPciWidthUint8) {
542 *(UINT8 *) (UINTN) Address = *(UINT8 *) Buffer;
543 Address += 1;
544 } else if (Width == EfiPciWidthUint16) {
545 *(UINT16 *) (UINTN) Address = *(UINT16 *) Buffer;
546 Address += 2;
547 } else if (Width == EfiPciWidthUint32) {
548 *(UINT32 *) (UINTN) Address = *(UINT32 *) Buffer;
549 Address += 4;
550 } else if (Width == EfiPciWidthUint64) {
551 *(UINT64 *) (UINTN) Address = *(UINT64 *) Buffer;
552 Address += 8;
553 } else {
554 ASSERT (FALSE);
555 }
556 //
557 //
558 //
559 Size--;
560 } while (Size > 0);
561 }
562
563 BOOLEAN
564 EFIAPI
565 GetHex (
566 IN UINT16 *str,
567 OUT UINT64 *data
568 )
569 {
570 UINTN u;
571 CHAR16 c;
572 BOOLEAN Find;
573
574 Find = FALSE;
575 //
576 // convert hex digits
577 //
578 u = 0;
579 c = *(str++);
580 while (c != CHAR_NULL) {
581 if (c >= 'a' && c <= 'f') {
582 c -= 'a' - 'A';
583 }
584
585 if (c == ' ') {
586 break;
587 }
588
589 if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
590 u = u << 4 | c - (c >= 'A' ? 'A' - 10 : '0');
591
592 Find = TRUE;
593 } else {
594 return FALSE;
595 }
596
597 c = *(str++);
598 }
599
600 *data = u;
601 return Find;
602 }