1 /** @file
2   Main file for Comp shell Debug1 function.
3 
4   (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
5   Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
6   This program and the accompanying materials
7   are licensed and made available under the terms and conditions of the BSD License
8   which accompanies this distribution.  The full text of the license may be found at
9   http://opensource.org/licenses/bsd-license.php
10 
11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include "UefiShellDebug1CommandsLib.h"
17 
18 /**
19   Function for 'comp' command.
20 
21   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
22   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
23 **/
24 SHELL_STATUS
25 EFIAPI
ShellCommandRunComp(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)26 ShellCommandRunComp (
27   IN EFI_HANDLE        ImageHandle,
28   IN EFI_SYSTEM_TABLE  *SystemTable
29   )
30 {
31   EFI_STATUS          Status;
32   LIST_ENTRY          *Package;
33   CHAR16              *ProblemParam;
34   SHELL_STATUS        ShellStatus;
35   UINTN               LoopVar;
36   SHELL_FILE_HANDLE   FileHandle1;
37   SHELL_FILE_HANDLE   FileHandle2;
38   UINT8               ErrorCount;
39   UINT64              Size1;
40   UINT64              Size2;
41   UINT8               DataFromFile1;
42   UINT8               DataFromFile2;
43   UINT8               ADF_File11;
44   UINT8               ADF_File12;
45   UINT8               ADF_File13;
46   UINT8               ADF_File21;
47   UINT8               ADF_File22;
48   UINT8               ADF_File23;
49   UINTN               DataSizeFromFile1;
50   UINTN               DataSizeFromFile2;
51   CHAR16              *FileName1;
52   CHAR16              *FileName2;
53   CONST CHAR16        *TempParam;
54   UINTN               ErrorAddress;
55 
56   ErrorCount          = 0;
57   ShellStatus         = SHELL_SUCCESS;
58   Status              = EFI_SUCCESS;
59   FileName1           = NULL;
60   FileName2           = NULL;
61   FileHandle1         = NULL;
62   FileHandle2         = NULL;
63   Size1               = 0;
64 
65   //
66   // initialize the shell lib (we must be in non-auto-init...)
67   //
68   Status = ShellInitialize();
69   ASSERT_EFI_ERROR(Status);
70 
71   Status = CommandInit();
72   ASSERT_EFI_ERROR(Status);
73 
74   //
75   // parse the command line
76   //
77   Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
78   if (EFI_ERROR(Status)) {
79     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
80       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"comp", ProblemParam);
81       FreePool(ProblemParam);
82       ShellStatus = SHELL_INVALID_PARAMETER;
83     } else {
84       ASSERT(FALSE);
85     }
86   } else {
87     if (ShellCommandLineGetCount(Package) > 3) {
88       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"comp");
89       ShellStatus = SHELL_INVALID_PARAMETER;
90     } else if (ShellCommandLineGetCount(Package) < 3) {
91       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"comp");
92       ShellStatus = SHELL_INVALID_PARAMETER;
93     } else {
94       TempParam = ShellCommandLineGetRawValue(Package, 1);
95       ASSERT(TempParam != NULL);
96       FileName1 = ShellFindFilePath(TempParam);
97       if (FileName1 == NULL) {
98         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_FIND_FAIL), gShellDebug1HiiHandle, L"comp", TempParam);
99         ShellStatus = SHELL_NOT_FOUND;
100       } else {
101         Status = ShellOpenFileByName(FileName1, &FileHandle1, EFI_FILE_MODE_READ, 0);
102         if (EFI_ERROR(Status)) {
103           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"comp", TempParam);
104           ShellStatus = SHELL_NOT_FOUND;
105         }
106       }
107       TempParam = ShellCommandLineGetRawValue(Package, 2);
108       ASSERT(TempParam != NULL);
109       FileName2 = ShellFindFilePath(TempParam);
110       if (FileName2 == NULL) {
111         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_FIND_FAIL), gShellDebug1HiiHandle, L"comp", TempParam);
112         ShellStatus = SHELL_NOT_FOUND;
113       } else {
114         Status = ShellOpenFileByName(FileName2, &FileHandle2, EFI_FILE_MODE_READ, 0);
115         if (EFI_ERROR(Status)) {
116           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"comp", TempParam);
117           ShellStatus = SHELL_NOT_FOUND;
118         }
119       }
120       if (ShellStatus == SHELL_SUCCESS) {
121         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_COMP_HEADER), gShellDebug1HiiHandle, FileName1, FileName2);
122         Status = gEfiShellProtocol->GetFileSize(FileHandle1, &Size1);
123         ASSERT_EFI_ERROR(Status);
124         Status = gEfiShellProtocol->GetFileSize(FileHandle2, &Size2);
125         ASSERT_EFI_ERROR(Status);
126         if (Size1 != Size2) {
127           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_COMP_SIZE_FAIL), gShellDebug1HiiHandle);
128           ErrorCount++;
129           ShellStatus = SHELL_NOT_EQUAL;
130         }
131       }
132       if (ShellStatus == SHELL_SUCCESS) {
133         for (LoopVar = 0 ; LoopVar < Size1 && ErrorCount <= 10 ; LoopVar++) {
134           DataSizeFromFile1 = 1;
135           DataSizeFromFile2 = 1;
136           Status = gEfiShellProtocol->ReadFile(FileHandle1, &DataSizeFromFile1, &DataFromFile1);
137           ASSERT_EFI_ERROR(Status);
138           Status = gEfiShellProtocol->ReadFile(FileHandle2, &DataSizeFromFile2, &DataFromFile2);
139           ASSERT_EFI_ERROR(Status);
140           if (DataFromFile1 != DataFromFile2) {
141             ErrorAddress = LoopVar;
142             ADF_File11 = 0;
143             ADF_File12 = 0;
144             ADF_File13 = 0;
145             ADF_File21 = 0;
146             ADF_File22 = 0;
147             ADF_File23 = 0;
148 
149             //
150             // Now check the next 3 bytes if possible.  This will make output
151             // cleaner when there are a sequence of differences.
152             //
153             if (LoopVar + 1 < Size1) {
154               LoopVar++;
155               DataSizeFromFile1 = 1;
156               DataSizeFromFile2 = 1;
157               Status = gEfiShellProtocol->ReadFile(FileHandle1, &DataSizeFromFile1, &ADF_File11);
158               ASSERT_EFI_ERROR(Status);
159               Status = gEfiShellProtocol->ReadFile(FileHandle2, &DataSizeFromFile2, &ADF_File21);
160               ASSERT_EFI_ERROR(Status);
161               if (LoopVar + 1 < Size1) {
162                 LoopVar++;
163                 DataSizeFromFile1 = 1;
164                 DataSizeFromFile2 = 1;
165                 Status = gEfiShellProtocol->ReadFile(FileHandle1, &DataSizeFromFile1, &ADF_File12);
166                 ASSERT_EFI_ERROR(Status);
167                 Status = gEfiShellProtocol->ReadFile(FileHandle2, &DataSizeFromFile2, &ADF_File22);
168                 ASSERT_EFI_ERROR(Status);
169                 if (LoopVar + 1 < Size1) {
170                   LoopVar++;
171                   DataSizeFromFile1 = 1;
172                   DataSizeFromFile2 = 1;
173                   Status = gEfiShellProtocol->ReadFile(FileHandle1, &DataSizeFromFile1, &ADF_File13);
174                   ASSERT_EFI_ERROR(Status);
175                   Status = gEfiShellProtocol->ReadFile(FileHandle2, &DataSizeFromFile2, &ADF_File23);
176                   ASSERT_EFI_ERROR(Status);
177                 }
178               }
179             }
180 
181             //
182             // Print out based on highest of the 4 bytes that are different.
183             //
184             if (ADF_File13 != ADF_File23) {
185               ShellPrintHiiEx(
186                 -1,
187                 -1,
188                 NULL,
189                 STRING_TOKEN (STR_COMP_SPOT_FAIL4),
190                 gShellDebug1HiiHandle,
191                 ++ErrorCount,
192                 FileName1,
193                 ErrorAddress,
194                 DataFromFile1, ADF_File11, ADF_File12, ADF_File13,
195                 DataFromFile1, ADF_File11, ADF_File12, ADF_File13,
196                 FileName2,
197                 ErrorAddress,
198                 DataFromFile2, ADF_File21, ADF_File22, ADF_File23,
199                 DataFromFile2, ADF_File21, ADF_File22, ADF_File23
200                );
201             } else if (ADF_File12 != ADF_File22) {
202               ShellPrintHiiEx(
203                 -1,
204                 -1,
205                 NULL,
206                 STRING_TOKEN (STR_COMP_SPOT_FAIL3),
207                 gShellDebug1HiiHandle,
208                 ++ErrorCount,
209                 FileName1,
210                 ErrorAddress,
211                 DataFromFile1, ADF_File11, ADF_File12,
212                 DataFromFile1, ADF_File11, ADF_File12,
213                 FileName2,
214                 ErrorAddress,
215                 DataFromFile2, ADF_File21, ADF_File22,
216                 DataFromFile2, ADF_File21, ADF_File22
217                );
218             } else if (ADF_File11 != ADF_File21) {
219               ShellPrintHiiEx(
220                 -1,
221                 -1,
222                 NULL,
223                 STRING_TOKEN (STR_COMP_SPOT_FAIL2),
224                 gShellDebug1HiiHandle,
225                 ++ErrorCount,
226                 FileName1,
227                 ErrorAddress,
228                 DataFromFile1, ADF_File11,
229                 DataFromFile1, ADF_File11,
230                 FileName2,
231                 ErrorAddress,
232                 DataFromFile2, ADF_File21,
233                 DataFromFile2, ADF_File21
234                );
235             } else {
236               ShellPrintHiiEx(
237                 -1,
238                 -1,
239                 NULL,
240                 STRING_TOKEN (STR_COMP_SPOT_FAIL1),
241                 gShellDebug1HiiHandle,
242                 ++ErrorCount,
243                 FileName1,
244                 ErrorAddress,
245                 DataFromFile1,
246                 DataFromFile1,
247                 FileName2,
248                 ErrorAddress,
249                 DataFromFile2,
250                 DataFromFile2
251                );
252             }
253             ShellStatus = SHELL_NOT_EQUAL;
254           }
255         }
256         if (ErrorCount == 0) {
257           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_COMP_FOOTER_PASS), gShellDebug1HiiHandle);
258         } else {
259           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_COMP_FOOTER_FAIL), gShellDebug1HiiHandle);
260         }
261       }
262     }
263 
264     ShellCommandLineFreeVarList (Package);
265   }
266   SHELL_FREE_NON_NULL(FileName1);
267   SHELL_FREE_NON_NULL(FileName2);
268 
269   if (FileHandle1 != NULL) {
270     gEfiShellProtocol->CloseFile(FileHandle1);
271   }
272   if (FileHandle2 != NULL) {
273     gEfiShellProtocol->CloseFile(FileHandle2);
274   }
275 
276   return (ShellStatus);
277 }
278