1 /*++
2 
3 Copyright (c) 2011  - 2014, Intel Corporation. All rights reserved
4 
5 
6   This program and the accompanying materials are licensed and made available under
7 
8   the terms and conditions of the BSD License that accompanies this distribution.
9 
10   The full text of the license may be found at
11 
12   http://opensource.org/licenses/bsd-license.php.
13 
14 
15 
16   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 
18   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 
20 
21 
22 
23 Module Name:
24 
25   BiosIdLib.c
26 
27 Abstract:
28 
29   Boot service DXE BIOS ID library implementation.
30 
31   These functions in this file can be called during DXE and cannot be called during runtime
32   or in SMM which should use a RT or SMM library.
33 
34 --*/
35 
36 #include <PiDxe.h>
37 #include <Library/BaseLib.h>
38 #include <Library/HobLib.h>
39 #include <Library/UefiBootServicesTableLib.h>
40 #include <Library/BaseMemoryLib.h>
GetImageFromFv(IN EFI_FIRMWARE_VOLUME2_PROTOCOL * Fv,IN EFI_GUID * NameGuid,IN EFI_SECTION_TYPE SectionType,OUT VOID ** Buffer,OUT UINTN * Size)41 #include <Library/DebugLib.h>
42 
43 #include <Library/BiosIdLib.h>
44 #include <Guid/BiosId.h>
45 #include <Protocol/FirmwareVolume2.h>
46 #include <Protocol/LoadedImage.h>
47 
48 
49 EFI_STATUS
50 GetImageFromFv (
51   IN  EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
52   IN  EFI_GUID           *NameGuid,
53   IN  EFI_SECTION_TYPE   SectionType,
54   OUT VOID               **Buffer,
55   OUT UINTN              *Size
56   )
57 {
58   EFI_STATUS                Status;
59   EFI_FV_FILETYPE           FileType;
60   EFI_FV_FILE_ATTRIBUTES    Attributes;
61   UINT32                    AuthenticationStatus;
62 
63   //
64   // Read desired section content in NameGuid file
65   //
66   *Buffer     = NULL;
67   *Size       = 0;
68   Status      = Fv->ReadSection (
69                       Fv,
70                       NameGuid,
71                       SectionType,
72                       0,
73                       Buffer,
74                       Size,
75                       &AuthenticationStatus
76                       );
77 
78   if (EFI_ERROR (Status) && (SectionType == EFI_SECTION_TE)) {
79     //
80     // Try reading PE32 section, since the TE section does not exist
81     //
82     *Buffer = NULL;
83     *Size   = 0;
84     Status  = Fv->ReadSection (
85                     Fv,
86                     NameGuid,
87                     EFI_SECTION_PE32,
88                     0,
89                     Buffer,
90                     Size,
91                     &AuthenticationStatus
92                     );
93   }
94 
95   if (EFI_ERROR (Status) &&
96       ((SectionType == EFI_SECTION_TE) || (SectionType == EFI_SECTION_PE32))) {
97     //
98     // Try reading raw file, since the desired section does not exist
99     //
100     *Buffer = NULL;
101     *Size   = 0;
102     Status  = Fv->ReadFile (
103                     Fv,
104                     NameGuid,
105                     Buffer,
106                     Size,
107                     &FileType,
108                     &Attributes,
109                     &AuthenticationStatus
110                     );
111   }
112 
113   return Status;
114 }
115 
116 
117 EFI_STATUS
118 GetImageEx (
119   IN  EFI_HANDLE         ImageHandle,
120   IN  EFI_GUID           *NameGuid,
121   IN  EFI_SECTION_TYPE   SectionType,
122   OUT VOID               **Buffer,
123   OUT UINTN              *Size,
124   BOOLEAN                WithinImageFv
125   )
126 {
127   EFI_STATUS                    Status;
128   EFI_HANDLE                    *HandleBuffer;
129   UINTN                         HandleCount;
130   UINTN                         Index;
131   EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
132 
133   EFI_FIRMWARE_VOLUME2_PROTOCOL *ImageFv;
134   EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
135 
136 
137   if (ImageHandle == NULL && WithinImageFv) {
138     return EFI_INVALID_PARAMETER;
139   }
140 
141   Status  = EFI_NOT_FOUND;
142   ImageFv = NULL;
143   if (ImageHandle != NULL) {
144     Status = gBS->HandleProtocol (
145                     ImageHandle,
146                     &gEfiLoadedImageProtocolGuid,
147                     (VOID **) &LoadedImage
148                     );
149     if (EFI_ERROR (Status)) {
150       return Status;
151     }
152     Status = gBS->HandleProtocol (
153                     LoadedImage->DeviceHandle,
154                     &gEfiFirmwareVolume2ProtocolGuid,
155                     (VOID **) &ImageFv
156                     );
157     if (!EFI_ERROR (Status)) {
158       Status = GetImageFromFv (ImageFv, NameGuid, SectionType, Buffer, Size);
159     }
160   }
161 
162   if (Status == EFI_SUCCESS || WithinImageFv) {
163     return Status;
164   }
165 
166   Status = gBS->LocateHandleBuffer (
167                   ByProtocol,
168                   &gEfiFirmwareVolume2ProtocolGuid,
169                   NULL,
170                   &HandleCount,
171                   &HandleBuffer
172                   );
173   if (EFI_ERROR (Status)) {
174     return Status;
175   }
176 
177   //
178   // Find desired image in all Fvs
179   //
180   for (Index = 0; Index < HandleCount; ++Index) {
181     Status = gBS->HandleProtocol (
182                     HandleBuffer[Index],
183                     &gEfiFirmwareVolume2ProtocolGuid,
184                     (VOID**)&Fv
185                     );
186 
187     if (EFI_ERROR (Status)) {
188       gBS->FreePool(HandleBuffer);
189       return Status;
190     }
191 
192     if (ImageFv != NULL && Fv == ImageFv) {
193       continue;
194     }
195 
196     Status = GetImageFromFv (Fv, NameGuid, SectionType, Buffer, Size);
197 
198     if (!EFI_ERROR (Status)) {
199       break;
200     }
201   }
202   gBS->FreePool(HandleBuffer);
203 
204   //
205   // Not found image
206   //
207   if (Index == HandleCount) {
208     return EFI_NOT_FOUND;
209   }
210 
211   return EFI_SUCCESS;
212 }
213 
214 /**
215   This function returns BIOS ID by searching HOB or FV.
GetBiosId(OUT BIOS_ID_IMAGE * BiosIdImage)216 
217   @param BiosIdImage             The BIOS ID got from HOB or FV.
218 
219   @retval EFI_SUCCESS            All parameters were valid and BIOS ID has been got.
220   @retval EFI_NOT_FOUND          BiosId image is not found, and no parameter will be modified.
221   @retval EFI_INVALID_PARAMETER  The parameter is NULL.
222 
223 **/
224 EFI_STATUS
225 GetBiosId (
226   OUT BIOS_ID_IMAGE     *BiosIdImage
227   )
228 
229 {
230   EFI_STATUS    Status;
231   VOID          *Address = NULL;
232   UINTN         Size = 0;
233 
234     DEBUG ((EFI_D_INFO, "Get BIOS ID from FV\n"));
235 
236     Status = GetImageEx (
237                NULL,
238                &gEfiBiosIdGuid,
239                EFI_SECTION_RAW,
240                &Address,
241                &Size,
242                FALSE
243                );
244 
245     if (Status == EFI_SUCCESS) {
246       //
247       // BiosId image is present in FV
248       //
249       if (Address != NULL) {
250         Size = sizeof (BIOS_ID_IMAGE);
251         gBS->CopyMem (
252               (void *) BiosIdImage,
253               Address,
254               Size
255               );
256         //
257         // GetImage () allocated buffer for Address, now clear it.
258         //
259         gBS->FreePool (Address);
260 
261         DEBUG ((EFI_D_INFO, "Get BIOS ID from FV successfully\n"));
262         DEBUG ((EFI_D_INFO, "BIOS ID: %s\n", (CHAR16 *) (&(BiosIdImage->BiosIdString))));
263 
264         return EFI_SUCCESS;
265       }
266     }
267   return EFI_NOT_FOUND;
268 }
269 
270 /**
271   This function returns the Version & Release Date and Time by getting and converting
272   BIOS ID.
273 
274   @param BiosVersion  The Bios Version out of the conversion.
GetBiosVersionDateTime(OUT CHAR16 * BiosVersion,OPTIONAL OUT CHAR16 * BiosReleaseDate,OPTIONAL OUT CHAR16 * BiosReleaseTime OPTIONAL)275   @param BiosReleaseDate  The Bios Release Date out of the conversion.
276   @param BiosReleaseTime - The Bios Release Time out of the conversion.
277 
278   @retval EFI_SUCCESS - BIOS Version & Release Date and Time have been got successfully.
279   @retval EFI_NOT_FOUND - BiosId image is not found, and no parameter will be modified.
280   @retval EFI_INVALID_PARAMETER - All the parameters are NULL.
281 
282 **/
283 EFI_STATUS
284 GetBiosVersionDateTime (
285   OUT CHAR16    *BiosVersion, OPTIONAL
286   OUT CHAR16    *BiosReleaseDate, OPTIONAL
287   OUT CHAR16    *BiosReleaseTime OPTIONAL
288   )
289 {
290   EFI_STATUS        Status;
291   BIOS_ID_IMAGE     BiosIdImage;
292 
293   if ((BiosVersion == NULL) && (BiosReleaseDate == NULL) && (BiosReleaseTime == NULL)) {
294     return EFI_INVALID_PARAMETER;
295   }
296 
297   Status = GetBiosId (&BiosIdImage);
298   if (EFI_ERROR (Status)) {
299     return EFI_NOT_FOUND;
300   }
301 
302   if (BiosVersion != NULL) {
303     //
304     // Fill the BiosVersion data from the BIOS ID.
305     //
306     StrCpy (BiosVersion, (CHAR16 *) (&(BiosIdImage.BiosIdString)));
307   }
308 
309   if (BiosReleaseDate != NULL) {
310     //
311     // Fill the build timestamp date from the BIOS ID in the "MM/DD/YY" format.
312     //
313     BiosReleaseDate[0] = BiosIdImage.BiosIdString.TimeStamp[2];
314     BiosReleaseDate[1] = BiosIdImage.BiosIdString.TimeStamp[3];
315     BiosReleaseDate[2] = (CHAR16) ((UINT8) ('/'));
316 
317     BiosReleaseDate[3] = BiosIdImage.BiosIdString.TimeStamp[4];
318     BiosReleaseDate[4] = BiosIdImage.BiosIdString.TimeStamp[5];
319     BiosReleaseDate[5] = (CHAR16) ((UINT8) ('/'));
320 
321     //
322     // Add 20 for SMBIOS table
323     // Current Linux kernel will misjudge 09 as year 0, so using 2009 for SMBIOS table
324     //
325     BiosReleaseDate[6] = '2';
326     BiosReleaseDate[7] = '0';
327     BiosReleaseDate[8] = BiosIdImage.BiosIdString.TimeStamp[0];
328     BiosReleaseDate[9] = BiosIdImage.BiosIdString.TimeStamp[1];
329 
330     BiosReleaseDate[10] = (CHAR16) ((UINT8) ('\0'));
331   }
332 
333   if (BiosReleaseTime != NULL) {
334 
335     //
336     // Fill the build timestamp time from the BIOS ID in the "HH:MM" format.
337     //
338 
339     BiosReleaseTime[0] = BiosIdImage.BiosIdString.TimeStamp[6];
340     BiosReleaseTime[1] = BiosIdImage.BiosIdString.TimeStamp[7];
341     BiosReleaseTime[2] = (CHAR16) ((UINT8) (':'));
342 
343     BiosReleaseTime[3] = BiosIdImage.BiosIdString.TimeStamp[8];
344     BiosReleaseTime[4] = BiosIdImage.BiosIdString.TimeStamp[9];
345 
346     BiosReleaseTime[5] = (CHAR16) ((UINT8) ('\0'));
347   }
348 
349   return  EFI_SUCCESS;
350 }
351 
352