1 /** @file 2 3 Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR> 4 Copyright (C) 2013, Red Hat, Inc. 5 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 "Uefi.h" 17 #include <Library/BaseLib.h> 18 #include <Library/BaseMemoryLib.h> 19 #include <Library/DebugLib.h> 20 #include <Library/IoLib.h> 21 #include <Library/QemuFwCfgLib.h> 22 #include <Library/MemoryAllocationLib.h> 23 #include <Library/UefiBootServicesTableLib.h> 24 25 #include "QemuFwCfgLibInternal.h" 26 27 28 /** 29 Reads an 8-bit I/O port fifo into a block of memory. 30 31 Reads the 8-bit I/O fifo port specified by Port. 32 33 The port is read Count times, and the read data is 34 stored in the provided Buffer. 35 36 This function must guarantee that all I/O read and write operations are 37 serialized. 38 39 If 8-bit I/O port operations are not supported, then ASSERT(). 40 41 @param Port The I/O port to read. 42 @param Count The number of times to read I/O port. 43 @param Buffer The buffer to store the read data into. 44 45 **/ 46 VOID 47 EFIAPI 48 IoReadFifo8 ( 49 IN UINTN Port, 50 IN UINTN Count, 51 OUT VOID *Buffer 52 ); 53 54 /** 55 Writes an 8-bit I/O port fifo from a block of memory. 56 57 Writes the 8-bit I/O fifo port specified by Port. 58 59 The port is written Count times, and the data are obtained 60 from the provided Buffer. 61 62 This function must guarantee that all I/O read and write operations are 63 serialized. 64 65 If 8-bit I/O port operations are not supported, then ASSERT(). 66 67 @param Port The I/O port to read. 68 @param Count The number of times to read I/O port. 69 @param Buffer The buffer to store the read data into. 70 71 **/ 72 VOID 73 EFIAPI 74 IoWriteFifo8 ( 75 IN UINTN Port, 76 IN UINTN Count, 77 OUT VOID *Buffer 78 ); 79 80 81 /** 82 Selects a firmware configuration item for reading. 83 84 Following this call, any data read from this item will start from 85 the beginning of the configuration item's data. 86 87 @param[in] QemuFwCfgItem - Firmware Configuration item to read 88 89 **/ 90 VOID 91 EFIAPI 92 QemuFwCfgSelectItem ( 93 IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem 94 ) 95 { 96 DEBUG ((EFI_D_INFO, "Select Item: 0x%x\n", (UINT16)(UINTN) QemuFwCfgItem)); 97 IoWrite16 (0x510, (UINT16)(UINTN) QemuFwCfgItem); 98 } 99 100 101 /** 102 Transfer an array of bytes using the DMA interface. 103 104 @param[in] Size Size in bytes to transfer. 105 @param[in,out] Buffer Buffer to read data into or write data from. May be 106 NULL if Size is zero. 107 @param[in] Write TRUE if writing to fw_cfg from Buffer, FALSE if 108 reading from fw_cfg into Buffer. 109 **/ 110 VOID 111 InternalQemuFwCfgDmaBytes ( 112 IN UINT32 Size, 113 IN OUT VOID *Buffer OPTIONAL, 114 IN BOOLEAN Write 115 ) 116 { 117 volatile FW_CFG_DMA_ACCESS Access; 118 UINT32 AccessHigh, AccessLow; 119 UINT32 Status; 120 121 if (Size == 0) { 122 return; 123 } 124 125 Access.Control = SwapBytes32 ( 126 Write ? FW_CFG_DMA_CTL_WRITE : FW_CFG_DMA_CTL_READ 127 ); 128 Access.Length = SwapBytes32 (Size); 129 Access.Address = SwapBytes64 ((UINTN)Buffer); 130 131 // 132 // Delimit the transfer from (a) modifications to Access, (b) in case of a 133 // write, from writes to Buffer by the caller. 134 // 135 MemoryFence (); 136 137 // 138 // Start the transfer. 139 // 140 AccessHigh = (UINT32)RShiftU64 ((UINTN)&Access, 32); 141 AccessLow = (UINT32)(UINTN)&Access; 142 IoWrite32 (0x514, SwapBytes32 (AccessHigh)); 143 IoWrite32 (0x518, SwapBytes32 (AccessLow)); 144 145 // 146 // Don't look at Access.Control before starting the transfer. 147 // 148 MemoryFence (); 149 150 // 151 // Wait for the transfer to complete. 152 // 153 do { 154 Status = SwapBytes32 (Access.Control); 155 ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0); 156 } while (Status != 0); 157 158 // 159 // After a read, the caller will want to use Buffer. 160 // 161 MemoryFence (); 162 } 163 164 165 /** 166 Reads firmware configuration bytes into a buffer 167 168 @param[in] Size - Size in bytes to read 169 @param[in] Buffer - Buffer to store data into (OPTIONAL if Size is 0) 170 171 **/ 172 VOID 173 EFIAPI 174 InternalQemuFwCfgReadBytes ( 175 IN UINTN Size, 176 IN VOID *Buffer OPTIONAL 177 ) 178 { 179 if (InternalQemuFwCfgDmaIsAvailable () && Size <= MAX_UINT32) { 180 InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, FALSE); 181 return; 182 } 183 IoReadFifo8 (0x511, Size, Buffer); 184 } 185 186 187 /** 188 Reads firmware configuration bytes into a buffer 189 190 If called multiple times, then the data read will 191 continue at the offset of the firmware configuration 192 item where the previous read ended. 193 194 @param[in] Size - Size in bytes to read 195 @param[in] Buffer - Buffer to store data into 196 197 **/ 198 VOID 199 EFIAPI 200 QemuFwCfgReadBytes ( 201 IN UINTN Size, 202 IN VOID *Buffer 203 ) 204 { 205 if (InternalQemuFwCfgIsAvailable ()) { 206 InternalQemuFwCfgReadBytes (Size, Buffer); 207 } else { 208 ZeroMem (Buffer, Size); 209 } 210 } 211 212 /** 213 Write firmware configuration bytes from a buffer 214 215 If called multiple times, then the data written will 216 continue at the offset of the firmware configuration 217 item where the previous write ended. 218 219 @param[in] Size - Size in bytes to write 220 @param[in] Buffer - Buffer to read data from 221 222 **/ 223 VOID 224 EFIAPI 225 QemuFwCfgWriteBytes ( 226 IN UINTN Size, 227 IN VOID *Buffer 228 ) 229 { 230 if (InternalQemuFwCfgIsAvailable ()) { 231 if (InternalQemuFwCfgDmaIsAvailable () && Size <= MAX_UINT32) { 232 InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, TRUE); 233 return; 234 } 235 IoWriteFifo8 (0x511, Size, Buffer); 236 } 237 } 238 239 240 /** 241 Reads a UINT8 firmware configuration value 242 243 @return Value of Firmware Configuration item read 244 245 **/ 246 UINT8 247 EFIAPI 248 QemuFwCfgRead8 ( 249 VOID 250 ) 251 { 252 UINT8 Result; 253 254 QemuFwCfgReadBytes (sizeof (Result), &Result); 255 256 return Result; 257 } 258 259 260 /** 261 Reads a UINT16 firmware configuration value 262 263 @return Value of Firmware Configuration item read 264 265 **/ 266 UINT16 267 EFIAPI 268 QemuFwCfgRead16 ( 269 VOID 270 ) 271 { 272 UINT16 Result; 273 274 QemuFwCfgReadBytes (sizeof (Result), &Result); 275 276 return Result; 277 } 278 279 280 /** 281 Reads a UINT32 firmware configuration value 282 283 @return Value of Firmware Configuration item read 284 285 **/ 286 UINT32 287 EFIAPI 288 QemuFwCfgRead32 ( 289 VOID 290 ) 291 { 292 UINT32 Result; 293 294 QemuFwCfgReadBytes (sizeof (Result), &Result); 295 296 return Result; 297 } 298 299 300 /** 301 Reads a UINT64 firmware configuration value 302 303 @return Value of Firmware Configuration item read 304 305 **/ 306 UINT64 307 EFIAPI 308 QemuFwCfgRead64 ( 309 VOID 310 ) 311 { 312 UINT64 Result; 313 314 QemuFwCfgReadBytes (sizeof (Result), &Result); 315 316 return Result; 317 } 318 319 320 /** 321 Find the configuration item corresponding to the firmware configuration file. 322 323 @param[in] Name - Name of file to look up. 324 @param[out] Item - Configuration item corresponding to the file, to be passed 325 to QemuFwCfgSelectItem (). 326 @param[out] Size - Number of bytes in the file. 327 328 @return RETURN_SUCCESS If file is found. 329 RETURN_NOT_FOUND If file is not found. 330 RETURN_UNSUPPORTED If firmware configuration is unavailable. 331 332 **/ 333 RETURN_STATUS 334 EFIAPI 335 QemuFwCfgFindFile ( 336 IN CONST CHAR8 *Name, 337 OUT FIRMWARE_CONFIG_ITEM *Item, 338 OUT UINTN *Size 339 ) 340 { 341 UINT32 Count; 342 UINT32 Idx; 343 344 if (!InternalQemuFwCfgIsAvailable ()) { 345 return RETURN_UNSUPPORTED; 346 } 347 348 QemuFwCfgSelectItem (QemuFwCfgItemFileDir); 349 Count = SwapBytes32 (QemuFwCfgRead32 ()); 350 351 for (Idx = 0; Idx < Count; ++Idx) { 352 UINT32 FileSize; 353 UINT16 FileSelect; 354 UINT16 FileReserved; 355 CHAR8 FName[QEMU_FW_CFG_FNAME_SIZE]; 356 357 FileSize = QemuFwCfgRead32 (); 358 FileSelect = QemuFwCfgRead16 (); 359 FileReserved = QemuFwCfgRead16 (); 360 (VOID) FileReserved; /* Force a do-nothing reference. */ 361 InternalQemuFwCfgReadBytes (sizeof (FName), FName); 362 363 if (AsciiStrCmp (Name, FName) == 0) { 364 *Item = SwapBytes16 (FileSelect); 365 *Size = SwapBytes32 (FileSize); 366 return RETURN_SUCCESS; 367 } 368 } 369 370 return RETURN_NOT_FOUND; 371 } 372 373 374 /** 375 Determine if S3 support is explicitly enabled. 376 377 @retval TRUE if S3 support is explicitly enabled. 378 FALSE otherwise. This includes unavailability of the firmware 379 configuration interface. 380 **/ 381 BOOLEAN 382 EFIAPI 383 QemuFwCfgS3Enabled ( 384 VOID 385 ) 386 { 387 RETURN_STATUS Status; 388 FIRMWARE_CONFIG_ITEM FwCfgItem; 389 UINTN FwCfgSize; 390 UINT8 SystemStates[6]; 391 392 Status = QemuFwCfgFindFile ("etc/system-states", &FwCfgItem, &FwCfgSize); 393 if (Status != RETURN_SUCCESS || FwCfgSize != sizeof SystemStates) { 394 return FALSE; 395 } 396 QemuFwCfgSelectItem (FwCfgItem); 397 QemuFwCfgReadBytes (sizeof SystemStates, SystemStates); 398 return (BOOLEAN) (SystemStates[3] & BIT7); 399 } 400