1 /*++
2 
3 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution.  The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8 
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 
12 Module Name:
13 
14   ReportStatusCode.c
15 
16 Abstract:
17 
18 --*/
19 
20 #include "Tiano.h"
21 #include "EfiDriverLib.h"
22 #include "PeiHob.h"
23 #include EFI_PROTOCOL_DEFINITION (DevicePath)
24 #include EFI_GUID_DEFINITION (Hob)
25 #include EFI_GUID_DEFINITION (StatusCodeDataTypeId)
26 #include EFI_ARCH_PROTOCOL_DEFINITION (StatusCode)
27 
28 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
29 
30 EFI_REPORT_STATUS_CODE gReportStatusCode = NULL;
31 
32 VOID
33 EFIAPI
OnStatusCodeInstall(IN EFI_EVENT Event,IN VOID * Context)34 OnStatusCodeInstall (
35   IN EFI_EVENT        Event,
36   IN VOID             *Context
37   )
38 {
39   EFI_STATUS                Status;
40   EFI_STATUS_CODE_PROTOCOL  *StatusCode;
41 
42   Status = gBS->LocateProtocol (&gEfiStatusCodeRuntimeProtocolGuid, NULL, (VOID **) &StatusCode);
43   if (!EFI_ERROR (Status)) {
44     gReportStatusCode = StatusCode->ReportStatusCode;
45   }
46 }
47 
48 EFI_STATUS
GetPeiProtocol(IN EFI_GUID * ProtocolGuid,IN VOID ** Interface)49 GetPeiProtocol (
50   IN EFI_GUID  *ProtocolGuid,
51   IN VOID      **Interface
52   )
53 /*++
54 
55 Routine Description:
56 
57   Searches for a Protocol Interface passed from PEI through a HOB
58 
59 Arguments:
60 
61   ProtocolGuid - The Protocol GUID to search for in the HOB List
62   Interface    - A pointer to the interface for the Protocol GUID
63 
64 Returns:
65 
66   EFI_SUCCESS   - The Protocol GUID was found and its interface is returned in Interface
67   EFI_NOT_FOUND - The Protocol GUID was not found in the HOB List
68 
69 --*/
70 {
71   EFI_STATUS            Status;
72   EFI_PEI_HOB_POINTERS  GuidHob;
73 
74   //
75   // Get Hob list
76   //
77   Status = EfiLibGetSystemConfigurationTable (&gEfiHobListGuid, (VOID **)  &GuidHob.Raw);
78   if (EFI_ERROR (Status)) {
79     return Status;
80   }
81 
82   for (Status = EFI_NOT_FOUND; EFI_ERROR (Status);) {
83     if (END_OF_HOB_LIST (GuidHob)) {
84       Status = EFI_NOT_FOUND;
85       break;
86     }
87 
88     if (GET_HOB_TYPE (GuidHob) == EFI_HOB_TYPE_GUID_EXTENSION) {
89       if (EfiCompareGuid (ProtocolGuid, &GuidHob.Guid->Name)) {
90         Status     = EFI_SUCCESS;
91         *Interface = (VOID *) *(UINTN *) (GuidHob.Guid + 1);
92       }
93     }
94 
95     GuidHob.Raw = GET_NEXT_HOB (GuidHob);
96   }
97 
98   return Status;
99 }
100 
101 #endif
102 
103 EFI_STATUS
EfiLibReportStatusCode(IN EFI_STATUS_CODE_TYPE Type,IN EFI_STATUS_CODE_VALUE Value,IN UINT32 Instance,IN EFI_GUID * CallerId OPTIONAL,IN EFI_STATUS_CODE_DATA * Data OPTIONAL)104 EfiLibReportStatusCode (
105   IN EFI_STATUS_CODE_TYPE     Type,
106   IN EFI_STATUS_CODE_VALUE    Value,
107   IN UINT32                   Instance,
108   IN EFI_GUID                 *CallerId OPTIONAL,
109   IN EFI_STATUS_CODE_DATA     *Data     OPTIONAL
110   )
111 /*++
112 
113 Routine Description:
114 
115   Report device path through status code.
116 
117 Arguments:
118 
119   Type        - Code type
120   Value       - Code value
121   Instance    - Instance number
122   CallerId    - Caller name
123   DevicePath  - Device path that to be reported
124 
125 Returns:
126 
127   Status code.
128 
129   EFI_OUT_OF_RESOURCES - No enough buffer could be allocated
130 
131 --*/
132 {
133   EFI_STATUS  Status;
134 
135 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
136   if (gReportStatusCode == NULL) {
137     //
138     // Because we've installed the protocol notification on EfiStatusCodeRuntimeProtocol,
139     //   running here indicates that the StatusCode driver has not started yet.
140     //
141     if (gBS == NULL) {
142       //
143       // Running here only when StatusCode driver never starts.
144       //
145       return EFI_UNSUPPORTED;
146     }
147 
148     //
149     // Try to get the PEI version of ReportStatusCode.
150     //
151     Status = GetPeiProtocol (&gEfiStatusCodeRuntimeProtocolGuid, (VOID **) &gReportStatusCode);
152     if (EFI_ERROR (Status) || (gReportStatusCode == NULL)) {
153       return EFI_UNSUPPORTED;
154     }
155   }
156   Status = gReportStatusCode (Type, Value, Instance, CallerId, Data);
157 #else
158   if (gRT == NULL) {
159     return EFI_UNSUPPORTED;
160   }
161   //
162   // Check whether EFI_RUNTIME_SERVICES has Tiano Extension
163   //
164   Status = EFI_UNSUPPORTED;
165   if (gRT->Hdr.Revision     == EFI_SPECIFICATION_VERSION     &&
166       gRT->Hdr.HeaderSize   == sizeof (EFI_RUNTIME_SERVICES) &&
167       gRT->ReportStatusCode != NULL) {
168     Status = gRT->ReportStatusCode (Type, Value, Instance, CallerId, Data);
169   }
170 #endif
171   return Status;
172 }
173 
174 EFI_STATUS
ReportStatusCodeWithDevicePath(IN EFI_STATUS_CODE_TYPE Type,IN EFI_STATUS_CODE_VALUE Value,IN UINT32 Instance,IN EFI_GUID * CallerId OPTIONAL,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)175 ReportStatusCodeWithDevicePath (
176   IN EFI_STATUS_CODE_TYPE     Type,
177   IN EFI_STATUS_CODE_VALUE    Value,
178   IN UINT32                   Instance,
179   IN EFI_GUID                 * CallerId OPTIONAL,
180   IN EFI_DEVICE_PATH_PROTOCOL * DevicePath
181   )
182 /*++
183 
184 Routine Description:
185 
186   Report device path through status code.
187 
188 Arguments:
189 
190   Type        - Code type
191   Value       - Code value
192   Instance    - Instance number
193   CallerId    - Caller name
194   DevicePath  - Device path that to be reported
195 
196 Returns:
197 
198   Status code.
199 
200   EFI_OUT_OF_RESOURCES - No enough buffer could be allocated
201 
202 --*/
203 {
204   UINT16                    Size;
205   UINT16                    DevicePathSize;
206   EFI_STATUS_CODE_DATA      *ExtendedData;
207   EFI_DEVICE_PATH_PROTOCOL  *ExtendedDevicePath;
208   EFI_STATUS                Status;
209 
210   DevicePathSize  = (UINT16) EfiDevicePathSize (DevicePath);
211   Size            = (UINT16) (DevicePathSize + sizeof (EFI_STATUS_CODE_DATA));
212   ExtendedData    = (EFI_STATUS_CODE_DATA *) EfiLibAllocatePool (Size);
213   if (ExtendedData == NULL) {
214     return EFI_OUT_OF_RESOURCES;
215   }
216 
217   ExtendedDevicePath = EfiConstructStatusCodeData (Size, &gEfiStatusCodeSpecificDataGuid, ExtendedData);
218   EfiCopyMem (ExtendedDevicePath, DevicePath, DevicePathSize);
219 
220   Status = EfiLibReportStatusCode (Type, Value, Instance, CallerId, (EFI_STATUS_CODE_DATA *) ExtendedData);
221 
222   gBS->FreePool (ExtendedData);
223   return Status;
224 }
225