1 /** @file
2   Main file for EfiDecompress shell Debug1 function.
3 
4   (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
5   Copyright (c) 2005 - 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 #include <Protocol/Decompress.h>
18 
19 
20 /**
21   Function for 'decompress' command.
22 
23   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
24   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
25 **/
26 SHELL_STATUS
27 EFIAPI
ShellCommandRunEfiDecompress(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)28 ShellCommandRunEfiDecompress (
29   IN EFI_HANDLE        ImageHandle,
30   IN EFI_SYSTEM_TABLE  *SystemTable
31   )
32 {
33   EFI_STATUS          Status;
34   LIST_ENTRY          *Package;
35   CHAR16              *ProblemParam;
36   SHELL_STATUS        ShellStatus;
37   SHELL_FILE_HANDLE   InFileHandle;
38   SHELL_FILE_HANDLE   OutFileHandle;
39   UINT32              OutSize;
40   UINTN               OutSizeTemp;
41   VOID                *OutBuffer;
42   UINTN               InSize;
43   VOID                *InBuffer;
44   CHAR16              *InFileName;
45   CONST CHAR16        *OutFileName;
46   UINT64              Temp64Bit;
47   UINT32              ScratchSize;
48   VOID                *ScratchBuffer;
49   EFI_DECOMPRESS_PROTOCOL *Decompress;
50   CONST CHAR16        *TempParam;
51 
52   InFileName          = NULL;
53   OutFileName         = NULL;
54   OutSize             = 0;
55   ShellStatus         = SHELL_SUCCESS;
56   Status              = EFI_SUCCESS;
57   OutBuffer           = NULL;
58   InBuffer            = NULL;
59   ScratchBuffer       = NULL;
60   InFileHandle        = NULL;
61   OutFileHandle       = NULL;
62 
63   //
64   // initialize the shell lib (we must be in non-auto-init...)
65   //
66   Status = ShellInitialize();
67   ASSERT_EFI_ERROR(Status);
68 
69   Status = CommandInit();
70   ASSERT_EFI_ERROR(Status);
71 
72   //
73   // parse the command line
74   //
75   Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
76   if (EFI_ERROR(Status)) {
77     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
78       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"efidecompress", ProblemParam);
79       FreePool(ProblemParam);
80       ShellStatus = SHELL_INVALID_PARAMETER;
81     } else {
82       ASSERT(FALSE);
83     }
84   } else {
85     if (ShellCommandLineGetCount(Package) > 3) {
86       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"efidecompress");
87       ShellStatus = SHELL_INVALID_PARAMETER;
88     } else if (ShellCommandLineGetCount(Package) < 3) {
89       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"efidecompress");
90       ShellStatus = SHELL_INVALID_PARAMETER;
91     } else {
92       TempParam = ShellCommandLineGetRawValue(Package, 1);
93       ASSERT(TempParam != NULL);
94       InFileName = ShellFindFilePath(TempParam);
95       OutFileName = ShellCommandLineGetRawValue(Package, 2);
96       if (InFileName == NULL) {
97         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_FIND_FAIL), gShellDebug1HiiHandle, L"efidecompress", TempParam);
98         ShellStatus = SHELL_NOT_FOUND;
99       } else {
100         if (ShellIsDirectory(InFileName) == EFI_SUCCESS){
101           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_DIR), gShellDebug1HiiHandle, L"efidecompress", InFileName);
102           ShellStatus = SHELL_INVALID_PARAMETER;
103         }
104         if (ShellIsDirectory(OutFileName) == EFI_SUCCESS){
105           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_DIR), gShellDebug1HiiHandle, L"efidecompress", OutFileName);
106           ShellStatus = SHELL_INVALID_PARAMETER;
107         }
108         if (ShellStatus == SHELL_SUCCESS) {
109           Status = ShellOpenFileByName(InFileName, &InFileHandle, EFI_FILE_MODE_READ, 0);
110           if (EFI_ERROR(Status)) {
111             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"efidecompress", ShellCommandLineGetRawValue(Package, 1));
112             ShellStatus = SHELL_NOT_FOUND;
113           }
114         }
115 
116         if (ShellStatus == SHELL_SUCCESS) {
117           Status = FileHandleGetSize(InFileHandle, &Temp64Bit);
118           ASSERT(Temp64Bit <= (UINT32)(-1));
119           InSize = (UINTN)Temp64Bit;
120           ASSERT_EFI_ERROR(Status);
121           InBuffer = AllocateZeroPool(InSize);
122           ASSERT(InBuffer != NULL);
123           Status = gEfiShellProtocol->ReadFile(InFileHandle, &InSize, InBuffer);
124           ASSERT_EFI_ERROR(Status);
125 
126           Status = gBS->LocateProtocol(&gEfiDecompressProtocolGuid, NULL, (VOID**)&Decompress);
127           ASSERT_EFI_ERROR(Status);
128 
129           Status = Decompress->GetInfo(Decompress, InBuffer, (UINT32)InSize, &OutSize, &ScratchSize);
130           if (EFI_ERROR(Status) || OutSize == 0) {
131             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_EFI_DECOMPRESS_NOPE), gShellDebug1HiiHandle, InFileName);
132             ShellStatus = SHELL_NOT_FOUND;
133           } else {
134             Status = ShellOpenFileByName(OutFileName, &OutFileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
135             if (EFI_ERROR(Status)) {
136               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_OPEN_FAIL), gShellDebug1HiiHandle, ShellCommandLineGetRawValue(Package, 2), Status);
137               ShellStatus = SHELL_NOT_FOUND;
138             } else {
139               OutBuffer = AllocateZeroPool(OutSize);
140               ScratchBuffer = AllocateZeroPool(ScratchSize);
141               ASSERT(OutBuffer != NULL);
142               ASSERT(ScratchBuffer != NULL);
143 
144               Status = Decompress->Decompress(Decompress, InBuffer, (UINT32)InSize, OutBuffer, OutSize, ScratchBuffer, ScratchSize);
145               ASSERT_EFI_ERROR(Status);
146 
147               if (EFI_ERROR(Status)) {
148                 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_EFI_DECOMPRESS_FAIL), gShellDebug1HiiHandle, Status);
149                 ShellStatus = SHELL_DEVICE_ERROR;
150               } else {
151                 OutSizeTemp = OutSize;
152                 Status = gEfiShellProtocol->WriteFile(OutFileHandle, &OutSizeTemp, OutBuffer);
153                 OutSize = (UINT32)OutSizeTemp;
154                 if (EFI_ERROR(Status)) {
155                   ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_WRITE_FAIL), gShellDebug1HiiHandle, L"efidecompress", OutFileName, Status);
156                   ShellStatus = SHELL_DEVICE_ERROR;
157                 }
158               }
159             }
160           }
161         }
162       }
163     }
164 
165     ShellCommandLineFreeVarList (Package);
166   }
167   if (InFileHandle != NULL) {
168     gEfiShellProtocol->CloseFile(InFileHandle);
169   }
170   if (OutFileHandle != NULL) {
171     gEfiShellProtocol->CloseFile(OutFileHandle);
172   }
173 
174   SHELL_FREE_NON_NULL(InFileName);
175   SHELL_FREE_NON_NULL(InBuffer);
176   SHELL_FREE_NON_NULL(OutBuffer);
177   SHELL_FREE_NON_NULL(ScratchBuffer);
178 
179   return (ShellStatus);
180 }
181