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 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 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 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 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