TianoCore EDK2 master
Loading...
Searching...
No Matches
Comp.c
Go to the documentation of this file.
1
11
12STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
13 { L"-n", TypeValue },
14 { L"-s", TypeValue },
15 { NULL, TypeMax }
16};
17
18typedef enum {
19 OutOfDiffPoint,
20 InDiffPoint,
21 InPrevDiffPoint
22} READ_STATUS;
23
24//
25// Buffer type, for reading both file operands in chunks.
26//
27typedef struct {
28 UINT8 *Data; // dynamically allocated buffer
29 UINTN Allocated; // the allocated size of Data
30 UINTN Next; // next position in Data to fetch a byte at
31 UINTN Left; // number of bytes left in Data for fetching at Next
33
45VOID
47 CONST CHAR16 *FileName,
48 CHAR16 *FileTag,
49 UINT8 *Buffer,
50 UINT64 BufferSize,
51 UINTN Address,
52 UINT64 DifferentBytes
53 )
54{
55 UINTN Index;
56
57 ShellPrintEx (-1, -1, L"%s: %s\r\n %08x:", FileTag, FileName, Address);
58
59 //
60 // Print data in hex-format.
61 //
62 for (Index = 0; Index < BufferSize; Index++) {
63 ShellPrintEx (-1, -1, L" %02x", Buffer[Index]);
64 }
65
66 if (BufferSize < DifferentBytes) {
67 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_COMP_END_OF_FILE), gShellDebug1HiiHandle);
68 }
69
70 ShellPrintEx (-1, -1, L" *");
71
72 //
73 // Print data in char-format.
74 //
75 for (Index = 0; Index < BufferSize; Index++) {
76 if ((Buffer[Index] >= 0x20) && (Buffer[Index] <= 0x7E)) {
77 ShellPrintEx (-1, -1, L"%c", Buffer[Index]);
78 } else {
79 //
80 // Print dots for control characters
81 //
82 ShellPrintEx (-1, -1, L".");
83 }
84 }
85
86 ShellPrintEx (-1, -1, L"*\r\n");
87}
88
98VOID
100 OUT FILE_BUFFER *FileBuffer
101 )
102{
103 FileBuffer->Allocated = PcdGet32 (PcdShellFileOperationSize);
104 FileBuffer->Data = AllocatePool (FileBuffer->Allocated);
105 FileBuffer->Left = 0;
106}
107
116STATIC
117VOID
119 IN OUT FILE_BUFFER *FileBuffer
120 )
121{
122 SHELL_FREE_NON_NULL (FileBuffer->Data);
123}
124
154STATIC
157 IN SHELL_FILE_HANDLE FileHandle,
158 IN OUT FILE_BUFFER *FileBuffer,
159 OUT UINTN *BytesRead,
160 OUT UINT8 *Byte
161 )
162{
163 UINTN ReadSize;
164 EFI_STATUS Status;
165
166 if (FileBuffer->Left == 0) {
167 ReadSize = FileBuffer->Allocated;
168 Status = gEfiShellProtocol->ReadFile (
169 FileHandle,
170 &ReadSize,
171 FileBuffer->Data
172 );
173 if (EFI_ERROR (Status)) {
174 return Status;
175 }
176
177 if (ReadSize == 0) {
178 *BytesRead = 0;
179 return EFI_SUCCESS;
180 }
181
182 FileBuffer->Next = 0;
183 FileBuffer->Left = ReadSize;
184 }
185
186 *BytesRead = 1;
187 *Byte = FileBuffer->Data[FileBuffer->Next];
188
189 FileBuffer->Next++;
190 FileBuffer->Left--;
191 return EFI_SUCCESS;
192}
193
201EFIAPI
203 IN EFI_HANDLE ImageHandle,
204 IN EFI_SYSTEM_TABLE *SystemTable
205 )
206{
207 EFI_STATUS Status;
208 LIST_ENTRY *Package;
209 CHAR16 *ProblemParam;
210 CHAR16 *FileName1;
211 CHAR16 *FileName2;
212 CONST CHAR16 *TempParam;
213 SHELL_STATUS ShellStatus;
214 SHELL_FILE_HANDLE FileHandle1;
215 SHELL_FILE_HANDLE FileHandle2;
216 UINT64 Size1;
217 UINT64 Size2;
218 UINT64 DifferentBytes;
219 UINT64 DifferentCount;
220 UINT8 DiffPointNumber;
221 UINT8 OneByteFromFile1;
222 UINT8 OneByteFromFile2;
223 UINT8 *DataFromFile1;
224 UINT8 *DataFromFile2;
225 FILE_BUFFER FileBuffer1;
226 FILE_BUFFER FileBuffer2;
227 UINTN InsertPosition1;
228 UINTN InsertPosition2;
229 UINTN DataSizeFromFile1;
230 UINTN DataSizeFromFile2;
231 UINTN TempAddress;
232 UINTN Index;
233 UINTN DiffPointAddress;
234 READ_STATUS ReadStatus;
235
236 ShellStatus = SHELL_SUCCESS;
237 Status = EFI_SUCCESS;
238 FileName1 = NULL;
239 FileName2 = NULL;
240 FileHandle1 = NULL;
241 FileHandle2 = NULL;
242 DataFromFile1 = NULL;
243 DataFromFile2 = NULL;
244 ReadStatus = OutOfDiffPoint;
245 DifferentCount = 10;
246 DifferentBytes = 4;
247 DiffPointNumber = 0;
248 InsertPosition1 = 0;
249 InsertPosition2 = 0;
250 TempAddress = 0;
251 DiffPointAddress = 0;
252
253 //
254 // initialize the shell lib (we must be in non-auto-init...)
255 //
256 Status = ShellInitialize ();
257 ASSERT_EFI_ERROR (Status);
258
259 Status = CommandInit ();
260 ASSERT_EFI_ERROR (Status);
261
262 //
263 // parse the command line
264 //
265 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
266 if (EFI_ERROR (Status)) {
267 if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {
268 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"comp", ProblemParam);
269 FreePool (ProblemParam);
270 ShellStatus = SHELL_INVALID_PARAMETER;
271 } else {
272 ASSERT (FALSE);
273 }
274 } else {
275 if (ShellCommandLineGetCount (Package) > 3) {
276 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"comp");
277 ShellStatus = SHELL_INVALID_PARAMETER;
278 } else if (ShellCommandLineGetCount (Package) < 3) {
279 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"comp");
280 ShellStatus = SHELL_INVALID_PARAMETER;
281 } else {
282 TempParam = ShellCommandLineGetRawValue (Package, 1);
283 if (TempParam == NULL) {
284 ASSERT (TempParam != NULL);
285 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"comp", TempParam);
286 ShellStatus = SHELL_INVALID_PARAMETER;
287 goto Exit;
288 }
289
290 FileName1 = ShellFindFilePath (TempParam);
291 if (FileName1 == NULL) {
292 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_FILE_FIND_FAIL), gShellDebug1HiiHandle, L"comp", TempParam);
293 ShellStatus = SHELL_NOT_FOUND;
294 } else {
295 Status = ShellOpenFileByName (FileName1, &FileHandle1, EFI_FILE_MODE_READ, 0);
296 if (EFI_ERROR (Status)) {
297 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"comp", TempParam);
298 ShellStatus = SHELL_NOT_FOUND;
299 }
300 }
301
302 TempParam = ShellCommandLineGetRawValue (Package, 2);
303 if (TempParam == NULL) {
304 ASSERT (TempParam != NULL);
305 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"comp", TempParam);
306 ShellStatus = SHELL_INVALID_PARAMETER;
307 goto Exit;
308 }
309
310 FileName2 = ShellFindFilePath (TempParam);
311 if (FileName2 == NULL) {
312 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_FILE_FIND_FAIL), gShellDebug1HiiHandle, L"comp", TempParam);
313 ShellStatus = SHELL_NOT_FOUND;
314 } else {
315 Status = ShellOpenFileByName (FileName2, &FileHandle2, EFI_FILE_MODE_READ, 0);
316 if (EFI_ERROR (Status)) {
317 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"comp", TempParam);
318 ShellStatus = SHELL_NOT_FOUND;
319 }
320 }
321
322 if (ShellStatus == SHELL_SUCCESS) {
323 Status = gEfiShellProtocol->GetFileSize (FileHandle1, &Size1);
324 ASSERT_EFI_ERROR (Status);
325 Status = gEfiShellProtocol->GetFileSize (FileHandle2, &Size2);
326 ASSERT_EFI_ERROR (Status);
327
328 if (ShellCommandLineGetFlag (Package, L"-n")) {
329 TempParam = ShellCommandLineGetValue (Package, L"-n");
330 if (TempParam == NULL) {
331 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"comp", L"-n");
332 ShellStatus = SHELL_INVALID_PARAMETER;
333 } else {
334 if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)TempParam, L"all") == 0) {
335 DifferentCount = MAX_UINTN;
336 } else {
337 Status = ShellConvertStringToUint64 (TempParam, &DifferentCount, FALSE, TRUE);
338 if (EFI_ERROR (Status) || (DifferentCount == 0)) {
339 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"comp", TempParam, L"-n");
340 ShellStatus = SHELL_INVALID_PARAMETER;
341 }
342 }
343 }
344 }
345
346 if (ShellCommandLineGetFlag (Package, L"-s")) {
347 TempParam = ShellCommandLineGetValue (Package, L"-s");
348 if (TempParam == NULL) {
349 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"comp", L"-s");
350 ShellStatus = SHELL_INVALID_PARAMETER;
351 } else {
352 Status = ShellConvertStringToUint64 (TempParam, &DifferentBytes, FALSE, TRUE);
353 if (EFI_ERROR (Status) || (DifferentBytes == 0)) {
354 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"comp", TempParam, L"-s");
355 ShellStatus = SHELL_INVALID_PARAMETER;
356 } else {
357 if (DifferentBytes > MAX (Size1, Size2)) {
358 DifferentBytes = MAX (Size1, Size2);
359 }
360 }
361 }
362 }
363 }
364
365 if (ShellStatus == SHELL_SUCCESS) {
366 DataFromFile1 = AllocateZeroPool ((UINTN)DifferentBytes);
367 DataFromFile2 = AllocateZeroPool ((UINTN)DifferentBytes);
368 FileBufferInit (&FileBuffer1);
369 FileBufferInit (&FileBuffer2);
370 if ((DataFromFile1 == NULL) || (DataFromFile2 == NULL) ||
371 (FileBuffer1.Data == NULL) || (FileBuffer2.Data == NULL))
372 {
373 ShellStatus = SHELL_OUT_OF_RESOURCES;
374 SHELL_FREE_NON_NULL (DataFromFile1);
375 SHELL_FREE_NON_NULL (DataFromFile2);
376 FileBufferUninit (&FileBuffer1);
377 FileBufferUninit (&FileBuffer2);
378 }
379 }
380
381 if (ShellStatus == SHELL_SUCCESS) {
382 while ((UINT64)DiffPointNumber < DifferentCount) {
383 DataSizeFromFile1 = 1;
384 DataSizeFromFile2 = 1;
385 OneByteFromFile1 = 0;
386 OneByteFromFile2 = 0;
387 Status = FileBufferReadByte (
388 FileHandle1,
389 &FileBuffer1,
390 &DataSizeFromFile1,
391 &OneByteFromFile1
392 );
393 ASSERT_EFI_ERROR (Status);
394 Status = FileBufferReadByte (
395 FileHandle2,
396 &FileBuffer2,
397 &DataSizeFromFile2,
398 &OneByteFromFile2
399 );
400 ASSERT_EFI_ERROR (Status);
401
402 TempAddress++;
403
404 //
405 // 1.When end of file and no chars in DataFromFile buffer, then break while.
406 // 2.If no more char in File1 or File2, The ReadStatus is InPrevDiffPoint forever.
407 // So the previous different point is the last one, then break the while block.
408 //
409 if (((DataSizeFromFile1 == 0) && (InsertPosition1 == 0) && (DataSizeFromFile2 == 0) && (InsertPosition2 == 0)) ||
410 ((ReadStatus == InPrevDiffPoint) && ((DataSizeFromFile1 == 0) || (DataSizeFromFile2 == 0)))
411 )
412 {
413 break;
414 }
415
416 if (ReadStatus == OutOfDiffPoint) {
417 if (OneByteFromFile1 != OneByteFromFile2) {
418 ReadStatus = InDiffPoint;
419 DiffPointAddress = TempAddress;
420 if (DataSizeFromFile1 == 1) {
421 DataFromFile1[InsertPosition1++] = OneByteFromFile1;
422 }
423
424 if (DataSizeFromFile2 == 1) {
425 DataFromFile2[InsertPosition2++] = OneByteFromFile2;
426 }
427 }
428 } else if (ReadStatus == InDiffPoint) {
429 if (DataSizeFromFile1 == 1) {
430 DataFromFile1[InsertPosition1++] = OneByteFromFile1;
431 }
432
433 if (DataSizeFromFile2 == 1) {
434 DataFromFile2[InsertPosition2++] = OneByteFromFile2;
435 }
436 } else if (ReadStatus == InPrevDiffPoint) {
437 if (OneByteFromFile1 == OneByteFromFile2) {
438 ReadStatus = OutOfDiffPoint;
439 }
440 }
441
442 //
443 // ReadStatus should be always equal InDiffPoint.
444 //
445 if ((InsertPosition1 == DifferentBytes) ||
446 (InsertPosition2 == DifferentBytes) ||
447 ((DataSizeFromFile1 == 0) && (DataSizeFromFile2 == 0))
448 )
449 {
450 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_COMP_DIFFERENCE_POINT), gShellDebug1HiiHandle, ++DiffPointNumber);
451 PrintDifferentPoint (FileName1, L"File1", DataFromFile1, InsertPosition1, DiffPointAddress, DifferentBytes);
452 PrintDifferentPoint (FileName2, L"File2", DataFromFile2, InsertPosition2, DiffPointAddress, DifferentBytes);
453
454 //
455 // One of two buffuers is empty, it means this is the last different point.
456 //
457 if ((InsertPosition1 == 0) || (InsertPosition2 == 0)) {
458 break;
459 }
460
461 for (Index = 1; Index < InsertPosition1 && Index < InsertPosition2; Index++) {
462 if (DataFromFile1[Index] == DataFromFile2[Index]) {
463 ReadStatus = OutOfDiffPoint;
464 break;
465 }
466 }
467
468 if (ReadStatus == OutOfDiffPoint) {
469 //
470 // Try to find a new different point in the rest of DataFromFile.
471 //
472 for ( ; Index < MAX (InsertPosition1, InsertPosition2); Index++) {
473 if (DataFromFile1[Index] != DataFromFile2[Index]) {
474 ReadStatus = InDiffPoint;
475 DiffPointAddress += Index;
476 break;
477 }
478 }
479 } else {
480 //
481 // Doesn't find a new different point, still in the same different point.
482 //
483 ReadStatus = InPrevDiffPoint;
484 }
485
486 CopyMem (DataFromFile1, DataFromFile1 + Index, InsertPosition1 - Index);
487 CopyMem (DataFromFile2, DataFromFile2 + Index, InsertPosition2 - Index);
488
489 SetMem (DataFromFile1 + InsertPosition1 - Index, (UINTN)DifferentBytes - InsertPosition1 + Index, 0);
490 SetMem (DataFromFile2 + InsertPosition2 - Index, (UINTN)DifferentBytes - InsertPosition2 + Index, 0);
491
492 InsertPosition1 -= Index;
493 InsertPosition2 -= Index;
494 }
495 }
496
497 SHELL_FREE_NON_NULL (DataFromFile1);
498 SHELL_FREE_NON_NULL (DataFromFile2);
499 FileBufferUninit (&FileBuffer1);
500 FileBufferUninit (&FileBuffer2);
501
502 if (DiffPointNumber == 0) {
503 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_COMP_FOOTER_PASS), gShellDebug1HiiHandle);
504 } else {
505 ShellStatus = SHELL_NOT_EQUAL;
506 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_COMP_FOOTER_FAIL), gShellDebug1HiiHandle);
507 }
508 }
509 }
510
512 }
513
514Exit:
515 SHELL_FREE_NON_NULL (FileName1);
516 SHELL_FREE_NON_NULL (FileName2);
517
518 if (FileHandle1 != NULL) {
519 gEfiShellProtocol->CloseFile (FileHandle1);
520 }
521
522 if (FileHandle2 != NULL) {
523 gEfiShellProtocol->CloseFile (FileHandle2);
524 }
525
526 return (ShellStatus);
527}
UINT64 UINTN
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
Definition: SetMemWrapper.c:38
STATIC VOID FileBufferInit(OUT FILE_BUFFER *FileBuffer)
Definition: Comp.c:99
STATIC VOID FileBufferUninit(IN OUT FILE_BUFFER *FileBuffer)
Definition: Comp.c:118
STATIC EFI_STATUS FileBufferReadByte(IN SHELL_FILE_HANDLE FileHandle, IN OUT FILE_BUFFER *FileBuffer, OUT UINTN *BytesRead, OUT UINT8 *Byte)
Definition: Comp.c:156
SHELL_STATUS EFIAPI ShellCommandRunComp(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: Comp.c:202
VOID PrintDifferentPoint(CONST CHAR16 *FileName, CHAR16 *FileTag, UINT8 *Buffer, UINT64 BufferSize, UINTN Address, UINT64 DifferentBytes)
Definition: Comp.c:46
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define MAX(a, b)
Definition: Base.h:992
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
SHELL_STATUS
Definition: Shell.h:21
@ SHELL_OUT_OF_RESOURCES
Definition: Shell.h:73
@ SHELL_SUCCESS
Definition: Shell.h:25
@ SHELL_NOT_FOUND
Definition: Shell.h:101
@ SHELL_NOT_EQUAL
Definition: Shell.h:147
@ SHELL_INVALID_PARAMETER
Definition: Shell.h:35
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
EFI_STATUS EFIAPI CommandInit(VOID)
CONST CHAR16 *EFIAPI ShellCommandLineGetValue(IN CONST LIST_ENTRY *CheckPackage, IN CHAR16 *KeyString)
#define ShellCommandLineParse(CheckList, CheckPackage, ProblemParam, AutoPageBreak)
Make it easy to upgrade from older versions of the shell library.
Definition: ShellLib.h:755
EFI_STATUS EFIAPI ShellPrintHiiEx(IN INT32 Col OPTIONAL, IN INT32 Row OPTIONAL, IN CONST CHAR8 *Language OPTIONAL, IN CONST EFI_STRING_ID HiiFormatStringId, IN CONST EFI_HII_HANDLE HiiFormatHandle,...)
BOOLEAN EFIAPI ShellCommandLineGetFlag(IN CONST LIST_ENTRY *CONST CheckPackage, IN CONST CHAR16 *CONST KeyString)
@ TypeValue
A flag that has some data following it with a space (IE "-a 1").
Definition: ShellLib.h:700
EFI_STATUS EFIAPI ShellOpenFileByName(IN CONST CHAR16 *FileName, OUT SHELL_FILE_HANDLE *FileHandle, IN UINT64 OpenMode, IN UINT64 Attributes)
Definition: UefiShellLib.c:720
VOID EFIAPI ShellCommandLineFreeVarList(IN LIST_ENTRY *CheckPackage)
EFI_STATUS EFIAPI ShellInitialize(VOID)
Definition: UefiShellLib.c:532
CHAR16 *EFIAPI ShellFindFilePath(IN CONST CHAR16 *FileName)
EFI_STATUS EFIAPI ShellPrintEx(IN INT32 Col OPTIONAL, IN INT32 Row OPTIONAL, IN CONST CHAR16 *Format,...)
CONST CHAR16 *EFIAPI ShellCommandLineGetRawValue(IN CONST LIST_ENTRY *CONST CheckPackage, IN UINTN Position)
UINTN EFIAPI ShellCommandLineGetCount(IN CONST LIST_ENTRY *CheckPackage)
EFI_STATUS EFIAPI ShellConvertStringToUint64(IN CONST CHAR16 *String, OUT UINT64 *Value, IN CONST BOOLEAN ForceHex, IN CONST BOOLEAN StopAtSpace)
EFI_STATUS EFIAPI ReadStatus(IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This, IN UINT32 LengthInBytes, OUT UINT8 *FlashStatus)
Definition: SpiNorFlash.c:707
VOID EFIAPI Exit(IN EFI_STATUS Status)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
#define STRING_TOKEN(t)