1 /** @file
2   FFS file access utilities.
3 
4 Copyright (c) 2006 - 2011, 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 
16 #include "DxeMain.h"
17 #include "FwVolDriver.h"
18 
19 
20 /**
21   Get the FFS file state by checking the highest bit set in the header's state field.
22 
23   @param  ErasePolarity  Erase polarity attribute of the firmware volume
24   @param  FfsHeader      Points to the FFS file header
25 
26   @return FFS File state
27 
28 **/
29 EFI_FFS_FILE_STATE
GetFileState(IN UINT8 ErasePolarity,IN EFI_FFS_FILE_HEADER * FfsHeader)30 GetFileState (
31   IN UINT8                ErasePolarity,
32   IN EFI_FFS_FILE_HEADER  *FfsHeader
33   )
34 {
35   EFI_FFS_FILE_STATE      FileState;
36   UINT8                   HighestBit;
37 
38   FileState = FfsHeader->State;
39 
40   if (ErasePolarity != 0) {
41     FileState = (EFI_FFS_FILE_STATE)~FileState;
42   }
43 
44   HighestBit = 0x80;
45   while (HighestBit != 0 && ((HighestBit & FileState) == 0)) {
46     HighestBit >>= 1;
47   }
48 
49   return (EFI_FFS_FILE_STATE) HighestBit;
50 }
51 
52 
53 
54 /**
55   Check if a block of buffer is erased.
56 
57   @param  ErasePolarity  Erase polarity attribute of the firmware volume
58   @param  InBuffer       The buffer to be checked
59   @param  BufferSize     Size of the buffer in bytes
60 
61   @retval TRUE           The block of buffer is erased
62   @retval FALSE          The block of buffer is not erased
63 
64 **/
65 BOOLEAN
IsBufferErased(IN UINT8 ErasePolarity,IN VOID * InBuffer,IN UINTN BufferSize)66 IsBufferErased (
67   IN UINT8    ErasePolarity,
68   IN VOID     *InBuffer,
69   IN UINTN    BufferSize
70   )
71 {
72   UINTN   Count;
73   UINT8   EraseByte;
74   UINT8   *Buffer;
75 
76   if(ErasePolarity == 1) {
77     EraseByte = 0xFF;
78   } else {
79     EraseByte = 0;
80   }
81 
82   Buffer = InBuffer;
83   for (Count = 0; Count < BufferSize; Count++) {
84     if (Buffer[Count] != EraseByte) {
85       return FALSE;
86     }
87   }
88 
89   return TRUE;
90 }
91 
92 
93 
94 /**
95   Verify checksum of the firmware volume header.
96 
97   @param  FvHeader       Points to the firmware volume header to be checked
98 
99   @retval TRUE           Checksum verification passed
100   @retval FALSE          Checksum verification failed
101 
102 **/
103 BOOLEAN
VerifyFvHeaderChecksum(IN EFI_FIRMWARE_VOLUME_HEADER * FvHeader)104 VerifyFvHeaderChecksum (
105   IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
106   )
107 {
108   UINT16  Checksum;
109 
110   Checksum = CalculateSum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength);
111 
112   if (Checksum == 0) {
113     return TRUE;
114   } else {
115     return FALSE;
116   }
117 }
118 
119 
120 /**
121   Verify checksum of the FFS file header.
122 
123   @param  FfsHeader      Points to the FFS file header to be checked
124 
125   @retval TRUE           Checksum verification passed
126   @retval FALSE          Checksum verification failed
127 
128 **/
129 BOOLEAN
VerifyHeaderChecksum(IN EFI_FFS_FILE_HEADER * FfsHeader)130 VerifyHeaderChecksum (
131   IN EFI_FFS_FILE_HEADER  *FfsHeader
132   )
133 {
134   UINT8 HeaderChecksum;
135 
136   if (IS_FFS_FILE2 (FfsHeader)) {
137     HeaderChecksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER2));
138   } else {
139     HeaderChecksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER));
140   }
141   HeaderChecksum = (UINT8) (HeaderChecksum - FfsHeader->State - FfsHeader->IntegrityCheck.Checksum.File);
142 
143   if (HeaderChecksum == 0) {
144     return TRUE;
145   } else {
146     return FALSE;
147   }
148 }
149 
150 
151 
152 /**
153   Check if it's a valid FFS file header.
154 
155   @param  ErasePolarity  Erase polarity attribute of the firmware volume
156   @param  FfsHeader      Points to the FFS file header to be checked
157   @param  FileState      FFS file state to be returned
158 
159   @retval TRUE           Valid FFS file header
160   @retval FALSE          Invalid FFS file header
161 
162 **/
163 BOOLEAN
IsValidFfsHeader(IN UINT8 ErasePolarity,IN EFI_FFS_FILE_HEADER * FfsHeader,OUT EFI_FFS_FILE_STATE * FileState)164 IsValidFfsHeader (
165   IN UINT8                ErasePolarity,
166   IN EFI_FFS_FILE_HEADER  *FfsHeader,
167   OUT EFI_FFS_FILE_STATE  *FileState
168   )
169 {
170   *FileState = GetFileState (ErasePolarity, FfsHeader);
171 
172   switch (*FileState) {
173   case EFI_FILE_HEADER_VALID:
174   case EFI_FILE_DATA_VALID:
175   case EFI_FILE_MARKED_FOR_UPDATE:
176   case EFI_FILE_DELETED:
177     //
178     // Here we need to verify header checksum
179     //
180     return VerifyHeaderChecksum (FfsHeader);
181 
182   case EFI_FILE_HEADER_CONSTRUCTION:
183   case EFI_FILE_HEADER_INVALID:
184   default:
185     return FALSE;
186   }
187 }
188 
189 
190 /**
191   Check if it's a valid FFS file.
192   Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first.
193 
194   @param  ErasePolarity  Erase polarity attribute of the firmware volume
195   @param  FfsHeader      Points to the FFS file to be checked
196 
197   @retval TRUE           Valid FFS file
198   @retval FALSE          Invalid FFS file
199 
200 **/
201 BOOLEAN
IsValidFfsFile(IN UINT8 ErasePolarity,IN EFI_FFS_FILE_HEADER * FfsHeader)202 IsValidFfsFile (
203   IN UINT8                ErasePolarity,
204   IN EFI_FFS_FILE_HEADER  *FfsHeader
205   )
206 {
207   EFI_FFS_FILE_STATE  FileState;
208   UINT8               DataCheckSum;
209 
210   FileState = GetFileState (ErasePolarity, FfsHeader);
211   switch (FileState) {
212 
213   case EFI_FILE_DELETED:
214   case EFI_FILE_DATA_VALID:
215   case EFI_FILE_MARKED_FOR_UPDATE:
216     DataCheckSum = FFS_FIXED_CHECKSUM;
217     if ((FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) == FFS_ATTRIB_CHECKSUM) {
218       if (IS_FFS_FILE2 (FfsHeader)) {
219         DataCheckSum = CalculateCheckSum8 ((CONST UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2), FFS_FILE2_SIZE (FfsHeader) - sizeof(EFI_FFS_FILE_HEADER2));
220       } else {
221         DataCheckSum = CalculateCheckSum8 ((CONST UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER), FFS_FILE_SIZE (FfsHeader) - sizeof(EFI_FFS_FILE_HEADER));
222       }
223     }
224     if (FfsHeader->IntegrityCheck.Checksum.File == DataCheckSum) {
225       return TRUE;
226     }
227 
228   default:
229     return FALSE;
230   }
231 }
232 
233 
234