]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c
Initialize Data.
[mirror_edk2.git] / MdeModulePkg / Library / PiDxeS3BootScriptLib / BootScriptExecute.c
1 /** @file
2 Interpret and execute the S3 data in S3 boot script.
3
4 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions
8 of the BSD License which accompanies this distribution. The
9 full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16 #include "InternalBootScriptLib.h"
17
18 /**
19 Checks the parameter of SmbusExecute().
20
21 This function checks the input parameters of SmbusExecute(). If the input parameters are valid
22 for certain SMBus bus protocol, it will return EFI_SUCCESS; otherwise, it will return certain
23 error code based on the input SMBus bus protocol.
24
25 @param SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length,
26 and PEC.
27 @param Operation Signifies which particular SMBus hardware protocol instance that
28 it will use to execute the SMBus transactions. This SMBus
29 hardware protocol is defined by the SMBus Specification and is
30 not related to EFI.
31 @param Length Signifies the number of bytes that this operation will do. The
32 maximum number of bytes can be revision specific and operation
33 specific. This field will contain the actual number of bytes that
34 are executed for this operation. Not all operations require this
35 argument.
36 @param Buffer Contains the value of data to execute to the SMBus slave device.
37 Not all operations require this argument. The length of this
38 buffer is identified by Length.
39
40 @retval EFI_SUCCESS All the parameters are valid for the corresponding SMBus bus
41 protocol.
42 @retval EFI_INVALID_PARAMETER Operation is not defined in EFI_SMBUS_OPERATION.
43 @retval EFI_INVALID_PARAMETER Length/Buffer is NULL for operations except for EfiSmbusQuickRead
44 and EfiSmbusQuickWrite. Length is outside the range of valid
45 values.
46 @retval EFI_UNSUPPORTED The SMBus operation or PEC is not supported.
47 @retval EFI_BUFFER_TOO_SMALL Buffer is not sufficient for this operation.
48
49 **/
50 EFI_STATUS
51 CheckParameters (
52 IN UINTN SmBusAddress,
53 IN EFI_SMBUS_OPERATION Operation,
54 IN OUT UINTN *Length,
55 IN OUT VOID *Buffer
56 )
57 {
58 EFI_STATUS Status;
59 UINTN RequiredLen;
60 EFI_SMBUS_DEVICE_COMMAND Command;
61 BOOLEAN PecCheck;
62
63 Command = SMBUS_LIB_COMMAND (SmBusAddress);
64 PecCheck = SMBUS_LIB_PEC (SmBusAddress);
65 //
66 // Set default value to be 2:
67 // for SmbusReadWord, SmbusWriteWord and SmbusProcessCall.
68 //
69 RequiredLen = 2;
70 Status = EFI_SUCCESS;
71 switch (Operation) {
72 case EfiSmbusQuickRead:
73 case EfiSmbusQuickWrite:
74 if (PecCheck || Command != 0) {
75 return EFI_UNSUPPORTED;
76 }
77 break;
78 case EfiSmbusReceiveByte:
79 case EfiSmbusSendByte:
80 if (Command != 0) {
81 return EFI_UNSUPPORTED;
82 }
83 //
84 // Cascade to check length parameter.
85 //
86 case EfiSmbusReadByte:
87 case EfiSmbusWriteByte:
88 RequiredLen = 1;
89 //
90 // Cascade to check length parameter.
91 //
92 case EfiSmbusReadWord:
93 case EfiSmbusWriteWord:
94 case EfiSmbusProcessCall:
95 if (Buffer == NULL || Length == NULL) {
96 return EFI_INVALID_PARAMETER;
97 } else if (*Length < RequiredLen) {
98 Status = EFI_BUFFER_TOO_SMALL;
99 }
100 *Length = RequiredLen;
101 break;
102 case EfiSmbusReadBlock:
103 case EfiSmbusWriteBlock:
104 if ((Buffer == NULL) ||
105 (Length == NULL) ||
106 (*Length < MIN_SMBUS_BLOCK_LEN) ||
107 (*Length > MAX_SMBUS_BLOCK_LEN)) {
108 return EFI_INVALID_PARAMETER;
109 }
110 break;
111 case EfiSmbusBWBRProcessCall:
112 return EFI_UNSUPPORTED;
113 default:
114 return EFI_INVALID_PARAMETER;
115 }
116 return Status;
117 }
118
119 /**
120 Executes an SMBus operation to an SMBus controller. Returns when either the command has been
121 executed or an error is encountered in doing the operation.
122
123 The SmbusExecute() function provides a standard way to execute an operation as defined in the System
124 Management Bus (SMBus) Specification. The resulting transaction will be either that the SMBus
125 slave devices accept this transaction or that this function returns with error.
126
127 @param SmbusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length,
128 and PEC.
129 @param Operation Signifies which particular SMBus hardware protocol instance that
130 it will use to execute the SMBus transactions. This SMBus
131 hardware protocol is defined by the SMBus Specification and is
132 not related to EFI.
133 @param Length Signifies the number of bytes that this operation will do. The
134 maximum number of bytes can be revision specific and operation
135 specific. This field will contain the actual number of bytes that
136 are executed for this operation. Not all operations require this
137 argument.
138 @param Buffer Contains the value of data to execute to the SMBus slave device.
139 Not all operations require this argument. The length of this
140 buffer is identified by Length.
141
142 @retval EFI_SUCCESS The last data that was returned from the access matched the poll
143 exit criteria.
144 @retval EFI_CRC_ERROR Checksum is not correct (PEC is incorrect).
145 @retval EFI_TIMEOUT Timeout expired before the operation was completed. Timeout is
146 determined by the SMBus host controller device.
147 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
148 @retval EFI_DEVICE_ERROR The request was not completed because a failure that was
149 reflected in the Host Status Register bit. Device errors are a
150 result of a transaction collision, illegal command field,
151 unclaimed cycle (host initiated), or bus errors (collisions).
152 @retval EFI_INVALID_PARAMETER Operation is not defined in EFI_SMBUS_OPERATION.
153 @retval EFI_INVALID_PARAMETER Length/Buffer is NULL for operations except for EfiSmbusQuickRead
154 and EfiSmbusQuickWrite. Length is outside the range of valid
155 values.
156 @retval EFI_UNSUPPORTED The SMBus operation or PEC is not supported.
157 @retval EFI_BUFFER_TOO_SMALL Buffer is not sufficient for this operation.
158
159 **/
160 EFI_STATUS
161 SmbusExecute (
162 IN UINTN SmbusAddress,
163 IN EFI_SMBUS_OPERATION Operation,
164 IN OUT UINTN *Length,
165 IN OUT VOID *Buffer
166 )
167 {
168 EFI_STATUS Status;
169 UINTN WorkBufferLen;
170 UINT8 WorkBuffer[MAX_SMBUS_BLOCK_LEN];
171
172 Status = CheckParameters (SmbusAddress, Operation, Length, Buffer);
173 if (EFI_ERROR (Status)) {
174 return Status;
175 }
176
177 switch (Operation) {
178 case EfiSmbusQuickRead:
179 DEBUG ((EFI_D_INFO, "EfiSmbusQuickRead - 0x%08x\n", SmbusAddress));
180 SmBusQuickRead (SmbusAddress, &Status);
181 break;
182 case EfiSmbusQuickWrite:
183 DEBUG ((EFI_D_INFO, "EfiSmbusQuickWrite - 0x%08x\n", SmbusAddress));
184 SmBusQuickWrite (SmbusAddress, &Status);
185 break;
186 case EfiSmbusReceiveByte:
187 DEBUG ((EFI_D_INFO, "EfiSmbusReceiveByte - 0x%08x\n", SmbusAddress));
188 *(UINT8 *) Buffer = SmBusReceiveByte (SmbusAddress, &Status);
189 break;
190 case EfiSmbusSendByte:
191 DEBUG ((EFI_D_INFO, "EfiSmbusReceiveByte - 0x%08x (0x%02x)\n", SmbusAddress, (UINTN)*(UINT8 *) Buffer));
192 SmBusSendByte (SmbusAddress, *(UINT8 *) Buffer, &Status);
193 break;
194 case EfiSmbusReadByte:
195 DEBUG ((EFI_D_INFO, "EfiSmbusReadByte - 0x%08x\n", SmbusAddress));
196 *(UINT8 *) Buffer = SmBusReadDataByte (SmbusAddress, &Status);
197 break;
198 case EfiSmbusWriteByte:
199 DEBUG ((EFI_D_INFO, "EfiSmbusWriteByte - 0x%08x (0x%02x)\n", SmbusAddress, (UINTN)*(UINT8 *) Buffer));
200 SmBusWriteDataByte (SmbusAddress, *(UINT8 *) Buffer, &Status);
201 break;
202 case EfiSmbusReadWord:
203 DEBUG ((EFI_D_INFO, "EfiSmbusReadWord - 0x%08x\n", SmbusAddress));
204 *(UINT16 *) Buffer = SmBusReadDataWord (SmbusAddress, &Status);
205 break;
206 case EfiSmbusWriteWord:
207 DEBUG ((EFI_D_INFO, "EfiSmbusWriteByte - 0x%08x (0x%04x)\n", SmbusAddress, (UINTN)*(UINT16 *) Buffer));
208 SmBusWriteDataWord (SmbusAddress, *(UINT16 *) Buffer, &Status);
209 break;
210 case EfiSmbusProcessCall:
211 DEBUG ((EFI_D_INFO, "EfiSmbusProcessCall - 0x%08x (0x%04x)\n", SmbusAddress, (UINTN)*(UINT16 *) Buffer));
212 *(UINT16 *) Buffer = SmBusProcessCall (SmbusAddress, *(UINT16 *) Buffer, &Status);
213 break;
214 case EfiSmbusReadBlock:
215 DEBUG ((EFI_D_INFO, "EfiSmbusReadBlock - 0x%08x\n", SmbusAddress));
216 WorkBufferLen = SmBusReadBlock (SmbusAddress, WorkBuffer, &Status);
217 if (!EFI_ERROR (Status)) {
218 //
219 // Read block transaction is complete successfully, and then
220 // check whether the output buffer is large enough.
221 //
222 if (*Length >= WorkBufferLen) {
223 CopyMem (Buffer, WorkBuffer, WorkBufferLen);
224 } else {
225 Status = EFI_BUFFER_TOO_SMALL;
226 }
227 *Length = WorkBufferLen;
228 }
229 break;
230 case EfiSmbusWriteBlock:
231 DEBUG ((EFI_D_INFO, "EfiSmbusWriteBlock - 0x%08x (0x%04x)\n", SmbusAddress, (UINTN)*(UINT16 *) Buffer));
232 SmBusWriteBlock ((SmbusAddress + SMBUS_LIB_ADDRESS (0, 0, (*Length), FALSE)) , Buffer, &Status);
233 break;
234 case EfiSmbusBWBRProcessCall:
235 //
236 // BUGBUG: Should this case be handled?
237 //
238 break;
239 }
240
241 return Status;
242 }
243
244 /**
245 Translates boot script width and address stride to MDE library interface.
246
247
248 @param Width Width of the operation.
249 @param Address Address of the operation.
250 @param AddressStride Instride for stepping input buffer.
251 @param BufferStride Outstride for stepping output buffer.
252
253 @retval EFI_SUCCESS Successful translation.
254 @retval EFI_INVALID_PARAMETER Width or Address is invalid.
255 **/
256 EFI_STATUS
257 BuildLoopData (
258 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
259 IN UINT64 Address,
260 OUT UINTN *AddressStride,
261 OUT UINTN *BufferStride
262 )
263 {
264 UINTN AlignMask;
265
266 if (Width >= S3BootScriptWidthMaximum) {
267 return EFI_INVALID_PARAMETER;
268 }
269
270 *AddressStride = (UINT32)(1 << (Width & 0x03));
271 *BufferStride = *AddressStride;
272
273 AlignMask = *AddressStride - 1;
274 if ((Address & AlignMask) != 0) {
275 return EFI_INVALID_PARAMETER;
276 }
277
278 if (Width >= S3BootScriptWidthFifoUint8 && Width <= S3BootScriptWidthFifoUint64) {
279 *AddressStride = 0;
280 }
281
282 if (Width >= S3BootScriptWidthFillUint8 && Width <= S3BootScriptWidthFillUint64) {
283 *BufferStride = 0;
284 }
285
286 return EFI_SUCCESS;
287 }
288
289 /**
290 Perform IO read operation
291
292 @param[in] Width Width of the operation.
293 @param[in] Address Address of the operation.
294 @param[in] Count Count of the number of accesses to perform.
295 @param[out] Buffer Pointer to the buffer to read from I/O space.
296
297 @retval EFI_SUCCESS The data was written to the EFI System.
298 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
299 Buffer is NULL.
300 The Buffer is not aligned for the given Width.
301 Address is outside the legal range of I/O ports.
302
303 **/
304 EFI_STATUS
305 ScriptIoRead (
306 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
307 IN UINT64 Address,
308 IN UINTN Count,
309 OUT VOID *Buffer
310 )
311 {
312 EFI_STATUS Status;
313 UINTN AddressStride;
314 UINTN BufferStride;
315 PTR Out;
316
317 Out.Buf = (UINT8 *) Buffer;
318
319 if (Address > MAX_IO_ADDRESS) {
320 return EFI_INVALID_PARAMETER;
321 }
322
323 Status = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
324 if (EFI_ERROR (Status)) {
325 return Status;
326 }
327 //
328 // Loop for each iteration and move the data
329 //
330 for (; Count > 0; Count--, Address += AddressStride, Out.Buf += BufferStride) {
331 switch (Width) {
332
333 case S3BootScriptWidthUint8:
334 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x\n", (UINTN) Address));
335 *Out.Uint8 = IoRead8 ((UINTN) Address);
336 break;
337 case S3BootScriptWidthFifoUint8:
338 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x\n", (UINTN) Address));
339 *Out.Uint8 = IoRead8 ((UINTN) Address);
340 break;
341 case S3BootScriptWidthFillUint8:
342 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x\n", (UINTN) Address));
343 *Out.Uint8 = IoRead8 ((UINTN) Address);
344 break;
345
346 case S3BootScriptWidthUint16:
347 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x\n", (UINTN) Address));
348 *Out.Uint16 = IoRead16 ((UINTN) Address);
349 break;
350 case S3BootScriptWidthFifoUint16:
351 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x\n", (UINTN) Address));
352 *Out.Uint16 = IoRead16 ((UINTN) Address);
353 break;
354 case S3BootScriptWidthFillUint16:
355 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x\n", (UINTN) Address));
356 *Out.Uint16 = IoRead16 ((UINTN) Address);
357 break;
358
359 case S3BootScriptWidthUint32:
360 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x\n", (UINTN) Address));
361 *Out.Uint32 = IoRead32 ((UINTN) Address);
362 break;
363 case S3BootScriptWidthFifoUint32:
364 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x\n", (UINTN) Address));
365 *Out.Uint32 = IoRead32 ((UINTN) Address);
366 break;
367 case S3BootScriptWidthFillUint32:
368 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x\n", (UINTN) Address));
369 *Out.Uint32 = IoRead32 ((UINTN) Address);
370 break;
371
372 case S3BootScriptWidthUint64:
373 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x\n", (UINTN) Address));
374 *Out.Uint64 = IoRead64 ((UINTN) Address);
375 break;
376 case S3BootScriptWidthFifoUint64:
377 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint64 - 0x%08x\n", (UINTN) Address));
378 *Out.Uint64 = IoRead64 ((UINTN) Address);
379 break;
380 case S3BootScriptWidthFillUint64:
381 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint64 - 0x%08x\n", (UINTN) Address));
382 *Out.Uint64 = IoRead64 ((UINTN) Address);
383 break;
384
385 default:
386 return EFI_INVALID_PARAMETER;
387 }
388 }
389
390 return EFI_SUCCESS;
391 }
392
393 /**
394 Perform IO write operation
395
396 @param[in] Width Width of the operation.
397 @param[in] Address Address of the operation.
398 @param[in] Count Count of the number of accesses to perform.
399 @param[in] Buffer Pointer to the buffer to write to I/O space.
400
401 @retval EFI_SUCCESS The data was written to the EFI System.
402 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
403 Buffer is NULL.
404 The Buffer is not aligned for the given Width.
405 Address is outside the legal range of I/O ports.
406
407 **/
408 EFI_STATUS
409 ScriptIoWrite (
410 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
411 IN UINT64 Address,
412 IN UINTN Count,
413 IN VOID *Buffer
414 )
415 {
416 EFI_STATUS Status;
417 UINTN AddressStride;
418 UINTN BufferStride;
419 UINT64 OriginalAddress;
420 PTR In;
421 PTR OriginalIn;
422
423 In.Buf = (UINT8 *) Buffer;
424
425 if (Address > MAX_IO_ADDRESS) {
426 return EFI_INVALID_PARAMETER;
427 }
428
429 Status = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
430 if (EFI_ERROR (Status)) {
431 return Status;
432 }
433 //
434 // Loop for each iteration and move the data
435 //
436 OriginalAddress = Address;
437 OriginalIn.Buf = In.Buf;
438 for (; Count > 0; Count--, Address += AddressStride, In.Buf += BufferStride) {
439 switch (Width) {
440 case S3BootScriptWidthUint8:
441 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*In.Uint8));
442 IoWrite8 ((UINTN) Address, *In.Uint8);
443 break;
444 case S3BootScriptWidthFifoUint8:
445 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x (0x%02x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint8));
446 IoWrite8 ((UINTN) OriginalAddress, *In.Uint8);
447 break;
448 case S3BootScriptWidthFillUint8:
449 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint8));
450 IoWrite8 ((UINTN) Address, *OriginalIn.Uint8);
451 break;
452 case S3BootScriptWidthUint16:
453 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*In.Uint16));
454 IoWrite16 ((UINTN) Address, *In.Uint16);
455 break;
456 case S3BootScriptWidthFifoUint16:
457 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x (0x%04x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint16));
458 IoWrite16 ((UINTN) OriginalAddress, *In.Uint16);
459 break;
460 case S3BootScriptWidthFillUint16:
461 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint16));
462 IoWrite16 ((UINTN) Address, *OriginalIn.Uint16);
463 break;
464 case S3BootScriptWidthUint32:
465 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*In.Uint32));
466 IoWrite32 ((UINTN) Address, *In.Uint32);
467 break;
468 case S3BootScriptWidthFifoUint32:
469 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x (0x%08x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint32));
470 IoWrite32 ((UINTN) OriginalAddress, *In.Uint32);
471 break;
472 case S3BootScriptWidthFillUint32:
473 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint32));
474 IoWrite32 ((UINTN) Address, *OriginalIn.Uint32);
475 break;
476 case S3BootScriptWidthUint64:
477 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *In.Uint64));
478 IoWrite64 ((UINTN) Address, *In.Uint64);
479 break;
480 case S3BootScriptWidthFifoUint64:
481 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint64 - 0x%08x (0x%016lx)\n", (UINTN)OriginalAddress, *In.Uint64));
482 IoWrite64 ((UINTN) OriginalAddress, *In.Uint64);
483 break;
484 case S3BootScriptWidthFillUint64:
485 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *OriginalIn.Uint64));
486 IoWrite64 ((UINTN) Address, *OriginalIn.Uint64);
487 break;
488 default:
489 return EFI_INVALID_PARAMETER;
490 }
491 }
492
493
494 return EFI_SUCCESS;
495 }
496 /**
497 Interprete the boot script node with EFI_BOOT_SCRIPT_IO_WRITE OP code.
498
499 @param Script Pointer to the node which is to be interpreted.
500
501 @retval EFI_SUCCESS The data was written to the EFI System.
502 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
503 Buffer is NULL.
504 The Buffer is not aligned for the given Width.
505 Address is outside the legal range of I/O ports.
506
507 **/
508 EFI_STATUS
509 BootScriptExecuteIoWrite (
510 IN UINT8 *Script
511 )
512 {
513 S3_BOOT_SCRIPT_LIB_WIDTH Width;
514 UINT64 Address;
515 UINTN Count;
516 VOID *Buffer;
517 EFI_BOOT_SCRIPT_IO_WRITE IoWrite;
518
519 CopyMem ((VOID*)&IoWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_IO_WRITE));
520 Width = (S3_BOOT_SCRIPT_LIB_WIDTH) IoWrite.Width;
521 Address = IoWrite.Address;
522 Count = IoWrite.Count;
523 Buffer = Script + sizeof (EFI_BOOT_SCRIPT_IO_WRITE);
524
525 DEBUG ((EFI_D_INFO, "BootScriptExecuteIoWrite - 0x%08x, 0x%08x, 0x%08x\n", (UINTN)Address, Count, (UINTN)Width));
526 return ScriptIoWrite(Width, Address, Count, Buffer);
527 }
528 /**
529 Perform memory read operation
530
531 @param Width Width of the operation.
532 @param Address Address of the operation.
533 @param Count Count of the number of accesses to perform.
534 @param Buffer Pointer to the buffer read from memory.
535
536 @retval EFI_SUCCESS The data was written to the EFI System.
537 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
538 Buffer is NULL.
539 The Buffer is not aligned for the given Width.
540 @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count
541 is not valid for this EFI System.
542
543 **/
544 EFI_STATUS
545 ScriptMemoryRead (
546 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
547 IN UINT64 Address,
548 IN UINTN Count,
549 IN OUT VOID *Buffer
550 )
551 {
552 EFI_STATUS Status;
553 UINTN AddressStride;
554 UINTN BufferStride;
555 PTR Out;
556
557 Out.Buf = Buffer;
558
559 Status = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
560 if (EFI_ERROR (Status)) {
561 return Status;
562 }
563 //
564 // Loop for each iteration and move the data
565 //
566 for (; Count > 0; Count--, Address += AddressStride, Out.Buf += BufferStride) {
567 switch (Width) {
568 case S3BootScriptWidthUint8:
569 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x\n", (UINTN)Address));
570 *Out.Uint8 = MmioRead8 ((UINTN) Address);
571 break;
572 case S3BootScriptWidthFifoUint8:
573 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x\n", (UINTN)Address));
574 *Out.Uint8 = MmioRead8 ((UINTN) Address);
575 break;
576 case S3BootScriptWidthFillUint8:
577 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x\n", (UINTN)Address));
578 *Out.Uint8 = MmioRead8 ((UINTN) Address);
579 break;
580
581 case S3BootScriptWidthUint16:
582 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x\n", (UINTN)Address));
583 *Out.Uint16 = MmioRead16 ((UINTN) Address);
584 break;
585 case S3BootScriptWidthFifoUint16:
586 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x\n", (UINTN)Address));
587 *Out.Uint16 = MmioRead16 ((UINTN) Address);
588 break;
589 case S3BootScriptWidthFillUint16:
590 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x\n", (UINTN)Address));
591 *Out.Uint16 = MmioRead16 ((UINTN) Address);
592 break;
593
594 case S3BootScriptWidthUint32:
595 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x\n", (UINTN)Address));
596 *Out.Uint32 = MmioRead32 ((UINTN) Address);
597 break;
598 case S3BootScriptWidthFifoUint32:
599 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x\n", (UINTN)Address));
600 *Out.Uint32 = MmioRead32 ((UINTN) Address);
601 break;
602 case S3BootScriptWidthFillUint32:
603 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x\n", (UINTN)Address));
604 *Out.Uint32 = MmioRead32 ((UINTN) Address);
605 break;
606
607 case S3BootScriptWidthUint64:
608 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x\n", (UINTN)Address));
609 *Out.Uint64 = MmioRead64 ((UINTN) Address);
610 break;
611 case S3BootScriptWidthFifoUint64:
612 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint64 - 0x%08x\n", (UINTN)Address));
613 *Out.Uint64 = MmioRead64 ((UINTN) Address);
614 break;
615 case S3BootScriptWidthFillUint64:
616 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint64 - 0x%08x\n", (UINTN)Address));
617 *Out.Uint64 = MmioRead64 ((UINTN) Address);
618 break;
619
620 default:
621 return EFI_UNSUPPORTED;
622 }
623 }
624
625 return EFI_SUCCESS;
626 }
627 /**
628 Perform memory write operation
629
630 @param Width Width of the operation.
631 @param Address Address of the operation.
632 @param Count Count of the number of accesses to perform.
633 @param Buffer Pointer to the buffer write to memory.
634
635 @retval EFI_SUCCESS The data was written to the EFI System.
636 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
637 Buffer is NULL.
638 The Buffer is not aligned for the given Width.
639 @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count
640 is not valid for this EFI System.
641
642 **/
643 EFI_STATUS
644 ScriptMemoryWrite (
645 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
646 IN UINT64 Address,
647 IN UINTN Count,
648 IN OUT VOID *Buffer
649 )
650 {
651 EFI_STATUS Status;
652 UINTN AddressStride;
653 UINT64 OriginalAddress;
654 UINTN BufferStride;
655 PTR In;
656 PTR OriginalIn;
657
658 In.Buf = Buffer;
659
660 Status = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
661 if (EFI_ERROR (Status)) {
662 return Status;
663 }
664 //
665 // Loop for each iteration and move the data
666 //
667 OriginalAddress = Address;
668 OriginalIn.Buf = In.Buf;
669 for (; Count > 0; Count--, Address += AddressStride, In.Buf += BufferStride) {
670 switch (Width) {
671 case S3BootScriptWidthUint8:
672 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*In.Uint8));
673 MmioWrite8 ((UINTN) Address, *In.Uint8);
674 break;
675 case S3BootScriptWidthFifoUint8:
676 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x (0x%02x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint8));
677 MmioWrite8 ((UINTN) OriginalAddress, *In.Uint8);
678 break;
679 case S3BootScriptWidthFillUint8:
680 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint8));
681 MmioWrite8 ((UINTN) Address, *OriginalIn.Uint8);
682 break;
683 case S3BootScriptWidthUint16:
684 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*In.Uint16));
685 MmioWrite16 ((UINTN) Address, *In.Uint16);
686 break;
687 case S3BootScriptWidthFifoUint16:
688 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x (0x%04x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint16));
689 MmioWrite16 ((UINTN) OriginalAddress, *In.Uint16);
690 break;
691 case S3BootScriptWidthFillUint16:
692 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint16));
693 MmioWrite16 ((UINTN) Address, *OriginalIn.Uint16);
694 break;
695 case S3BootScriptWidthUint32:
696 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*In.Uint32));
697 MmioWrite32 ((UINTN) Address, *In.Uint32);
698 break;
699 case S3BootScriptWidthFifoUint32:
700 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x (0x%08x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint32));
701 MmioWrite32 ((UINTN) OriginalAddress, *In.Uint32);
702 break;
703 case S3BootScriptWidthFillUint32:
704 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint32));
705 MmioWrite32 ((UINTN) Address, *OriginalIn.Uint32);
706 break;
707 case S3BootScriptWidthUint64:
708 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *In.Uint64));
709 MmioWrite64 ((UINTN) Address, *In.Uint64);
710 break;
711 case S3BootScriptWidthFifoUint64:
712 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint64 - 0x%08x (0x%016lx)\n", (UINTN)OriginalAddress, *In.Uint64));
713 MmioWrite64 ((UINTN) OriginalAddress, *In.Uint64);
714 break;
715 case S3BootScriptWidthFillUint64:
716 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *OriginalIn.Uint64));
717 MmioWrite64 ((UINTN) Address, *OriginalIn.Uint64);
718 break;
719 default:
720 return EFI_UNSUPPORTED;
721 }
722 }
723 return EFI_SUCCESS;
724 }
725 /**
726 Interprete the boot script node with EFI_BOOT_SCRIPT_MEM_WRITE OP code.
727
728 @param[in] Script Pointer to the node which is to be interpreted.
729
730 @retval EFI_SUCCESS The data was written to the EFI System.
731 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
732 Buffer is NULL.
733 The Buffer is not aligned for the given Width.
734 @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count
735 is not valid for this EFI System.
736
737 **/
738 EFI_STATUS
739 BootScriptExecuteMemoryWrite (
740 IN UINT8 *Script
741 )
742 {
743 VOID *Buffer;
744 S3_BOOT_SCRIPT_LIB_WIDTH Width;
745 UINT64 Address;
746 UINTN Count;
747 EFI_BOOT_SCRIPT_MEM_WRITE MemWrite;
748
749 CopyMem((VOID*)&MemWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_MEM_WRITE));
750 Width = (S3_BOOT_SCRIPT_LIB_WIDTH)MemWrite.Width;
751 Address = MemWrite.Address;
752 Count = MemWrite.Count;
753 Buffer = Script + sizeof(EFI_BOOT_SCRIPT_MEM_WRITE);
754
755 DEBUG ((EFI_D_INFO, "BootScriptExecuteMemoryWrite - 0x%08x, 0x%08x, 0x%08x\n", (UINTN)Address, Count, (UINTN)Width));
756 return ScriptMemoryWrite (Width,Address, Count, Buffer);
757
758 }
759 /**
760 Performance PCI configuration read operation
761
762 @param Width Width of the operation.
763 @param Address Address of the operation.
764 @param Count Count of the number of accesses to perform.
765 @param Buffer Pointer to the buffer read from PCI config space
766
767 @retval EFI_SUCCESS The read succeed.
768 @retval EFI_INVALID_PARAMETER if Width is not defined
769
770 **/
771 EFI_STATUS
772 ScriptPciCfgRead (
773 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
774 IN UINT64 Address,
775 IN UINTN Count,
776 OUT VOID *Buffer
777 )
778 {
779 EFI_STATUS Status;
780 UINTN AddressStride;
781 UINTN BufferStride;
782 PTR Out;
783 UINTN PciAddress;
784
785 Out.Buf = (UINT8 *) Buffer;
786
787 PciAddress = PCI_ADDRESS_ENCODE (Address);
788
789 Status = BuildLoopData (Width, PciAddress, &AddressStride, &BufferStride);
790 if (EFI_ERROR (Status)) {
791 return Status;
792 }
793 //
794 // Loop for each iteration and move the data
795 //
796 for (; Count > 0; Count--, PciAddress += AddressStride, Out.Buf += BufferStride) {
797 switch (Width) {
798 case S3BootScriptWidthUint8:
799 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x\n", PciAddress));
800 *Out.Uint8 = PciRead8 (PciAddress);
801 break;
802 case S3BootScriptWidthFifoUint8:
803 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x\n", PciAddress));
804 *Out.Uint8 = PciRead8 (PciAddress);
805 break;
806 case S3BootScriptWidthFillUint8:
807 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x\n", PciAddress));
808 *Out.Uint8 = PciRead8 (PciAddress);
809 break;
810
811 case S3BootScriptWidthUint16:
812 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x\n", PciAddress));
813 *Out.Uint16 = PciRead16 (PciAddress);
814 break;
815 case S3BootScriptWidthFifoUint16:
816 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x\n", PciAddress));
817 *Out.Uint16 = PciRead16 (PciAddress);
818 break;
819 case S3BootScriptWidthFillUint16:
820 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x\n", PciAddress));
821 *Out.Uint16 = PciRead16 (PciAddress);
822 break;
823
824 case S3BootScriptWidthUint32:
825 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x\n", PciAddress));
826 *Out.Uint32 = PciRead32 (PciAddress);
827 break;
828 case S3BootScriptWidthFifoUint32:
829 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x\n", PciAddress));
830 *Out.Uint32 = PciRead32 (PciAddress);
831 break;
832 case S3BootScriptWidthFillUint32:
833 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x\n", PciAddress));
834 *Out.Uint32 = PciRead32 (PciAddress);
835 break;
836
837 default:
838 return EFI_INVALID_PARAMETER;
839 }
840 }
841 return EFI_SUCCESS;
842 }
843
844 /**
845 Performance PCI configuration write operation
846
847 @param Width Width of the operation.
848 @param Address Address of the operation.
849 @param Count Count of the number of accesses to perform.
850 @param Buffer Pointer to the buffer write to PCI config space
851
852 @retval EFI_SUCCESS The write succeed.
853 @retval EFI_INVALID_PARAMETER if Width is not defined
854
855 **/
856 EFI_STATUS
857 ScriptPciCfgWrite (
858 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
859 IN UINT64 Address,
860 IN UINTN Count,
861 IN VOID *Buffer
862 )
863 {
864 EFI_STATUS Status;
865 UINTN AddressStride;
866 UINTN BufferStride;
867 UINTN OriginalPciAddress;
868 PTR In;
869 PTR OriginalIn;
870 UINTN PciAddress;
871
872 In.Buf = (UINT8 *) Buffer;
873
874 PciAddress = PCI_ADDRESS_ENCODE (Address);
875
876 Status = BuildLoopData (Width, PciAddress, &AddressStride, &BufferStride);
877 if (EFI_ERROR (Status)) {
878 return Status;
879 }
880 //
881 // Loop for each iteration and move the data
882 //
883 OriginalPciAddress = PciAddress;
884 OriginalIn.Buf = In.Buf;
885 for (; Count > 0; Count--, PciAddress += AddressStride, In.Buf += BufferStride) {
886 switch (Width) {
887 case S3BootScriptWidthUint8:
888 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x (0x%02x)\n", PciAddress, (UINTN)*In.Uint8));
889 PciWrite8 (PciAddress, *In.Uint8);
890 break;
891 case S3BootScriptWidthFifoUint8:
892 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x (0x%02x)\n", OriginalPciAddress, (UINTN)*In.Uint8));
893 PciWrite8 (OriginalPciAddress, *In.Uint8);
894 break;
895 case S3BootScriptWidthFillUint8:
896 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x (0x%02x)\n", PciAddress, (UINTN)*OriginalIn.Uint8));
897 PciWrite8 (PciAddress, *OriginalIn.Uint8);
898 break;
899 case S3BootScriptWidthUint16:
900 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x (0x%04x)\n", PciAddress, (UINTN)*In.Uint16));
901 PciWrite16 (PciAddress, *In.Uint16);
902 break;
903 case S3BootScriptWidthFifoUint16:
904 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x (0x%04x)\n", OriginalPciAddress, (UINTN)*In.Uint16));
905 PciWrite16 (OriginalPciAddress, *In.Uint16);
906 break;
907 case S3BootScriptWidthFillUint16:
908 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x (0x%04x)\n", PciAddress, (UINTN)*OriginalIn.Uint16));
909 PciWrite16 (PciAddress, *OriginalIn.Uint16);
910 break;
911 case S3BootScriptWidthUint32:
912 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x (0x%08x)\n", PciAddress, (UINTN)*In.Uint32));
913 PciWrite32 (PciAddress, *In.Uint32);
914 break;
915 case S3BootScriptWidthFifoUint32:
916 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x (0x%08x)\n", OriginalPciAddress, (UINTN)*In.Uint32));
917 PciWrite32 (OriginalPciAddress, *In.Uint32);
918 break;
919 case S3BootScriptWidthFillUint32:
920 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x (0x%08x)\n", (UINTN)PciAddress, (UINTN)*OriginalIn.Uint32));
921 PciWrite32 (PciAddress, *OriginalIn.Uint32);
922 break;
923 default:
924 return EFI_INVALID_PARAMETER;
925 }
926 }
927 return EFI_SUCCESS;
928 }
929 /**
930 Performance PCI configuration 2 read operation
931
932 @param Width Width of the operation.
933 @param Segment Pci segment number
934 @param Address Address of the operation.
935 @param Count Count of the number of accesses to perform.
936 @param Buffer Pointer to the buffer to read from PCI config space.
937
938 @retval EFI_SUCCESS The data was written to the EFI System.
939 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
940 Buffer is NULL.
941 The Buffer is not aligned for the given Width.
942 Address is outside the legal range of I/O ports.
943 @note A known Limitations in the implementation which is the 'Segment' parameter is assumed as
944 Zero, or else, assert.
945 **/
946 EFI_STATUS
947 ScriptPciCfg2Read (
948 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
949 IN UINT16 Segment,
950 IN UINT64 Address,
951 IN UINTN Count,
952 OUT VOID *Buffer
953 )
954 {
955 ASSERT (Segment==0);
956
957 return ScriptPciCfgRead (Width, Address, Count, Buffer);
958 }
959 /**
960 Performance PCI configuration 2 write operation
961
962 @param Width Width of the operation.
963 @param Segment Pci segment number
964 @param Address Address of the operation.
965 @param Count Count of the number of accesses to perform.
966 @param Buffer Pointer to the buffer to write to PCI config space.
967
968 @retval EFI_SUCCESS The data was written to the EFI System.
969 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
970 Buffer is NULL.
971 The Buffer is not aligned for the given Width.
972 Address is outside the legal range of I/O ports.
973 @note A known Limitations in the implementation which is the 'Segment' parameter is assumed as
974 Zero, or else, assert.
975
976 **/
977 EFI_STATUS
978 EFIAPI
979 ScriptPciCfg2Write (
980 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
981 IN UINT16 Segment,
982 IN UINT64 Address,
983 IN UINTN Count,
984 IN VOID *Buffer
985 )
986 {
987 ASSERT (Segment==0);
988 return ScriptPciCfgWrite (Width, Address, Count, Buffer);
989 }
990 /**
991 Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE OP code.
992
993 @param Script The pointer of typed node in boot script table
994
995 @retval EFI_SUCCESS The operation was executed successfully
996 **/
997 EFI_STATUS
998 BootScriptExecutePciCfgWrite (
999 IN UINT8 *Script
1000 )
1001 {
1002 VOID *Buffer;
1003 S3_BOOT_SCRIPT_LIB_WIDTH Width;
1004 UINT64 Address;
1005 UINTN Count;
1006 EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE PciCfgWrite;
1007
1008 CopyMem ((VOID*)&PciCfgWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE));
1009
1010 Width = (S3_BOOT_SCRIPT_LIB_WIDTH)PciCfgWrite.Width;
1011 Address = PciCfgWrite.Address;
1012 Count = PciCfgWrite.Count;
1013 Buffer = Script + sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE);
1014
1015 DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfgWrite - 0x%08x, 0x%08x, 0x%08x\n", PCI_ADDRESS_ENCODE (Address), Count, (UINTN)Width));
1016 return ScriptPciCfgWrite (Width, Address, Count, Buffer);
1017 }
1018 /**
1019 Interprete the boot script node with EFI_BOOT_SCRIPT_IO_READ_WRITE OP code.
1020
1021 @param Script The pointer of typed node in boot script table
1022 @param AndMask Mask value for 'and' operation
1023 @param OrMask Mask value for 'or' operation
1024
1025 @retval EFI_SUCCESS The operation was executed successfully
1026 **/
1027 EFI_STATUS
1028 BootScriptExecuteIoReadWrite (
1029 IN UINT8 *Script,
1030 IN UINT64 AndMask,
1031 IN UINT64 OrMask
1032 )
1033
1034 {
1035 EFI_STATUS Status;
1036 UINT64 Data;
1037 EFI_BOOT_SCRIPT_IO_READ_WRITE IoReadWrite;
1038
1039 Data = 0;
1040
1041 CopyMem((VOID*)&IoReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_IO_READ_WRITE));
1042
1043 DEBUG ((EFI_D_INFO, "BootScriptExecuteIoReadWrite - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)IoReadWrite.Address, AndMask, OrMask));
1044
1045 Status = ScriptIoRead (
1046 (S3_BOOT_SCRIPT_LIB_WIDTH) IoReadWrite.Width,
1047 IoReadWrite.Address,
1048 1,
1049 &Data
1050 );
1051 if (!EFI_ERROR (Status)) {
1052 Data = (Data & AndMask) | OrMask;
1053 Status = ScriptIoWrite (
1054 (S3_BOOT_SCRIPT_LIB_WIDTH) IoReadWrite.Width,
1055 IoReadWrite.Address,
1056 1,
1057 &Data
1058 );
1059 }
1060 return Status;
1061 }
1062 /**
1063 Interprete the boot script node with EFI_BOOT_SCRIPT_MEM_READ_WRITE OP code.
1064
1065 @param Script The pointer of typed node in boot script table
1066 @param AndMask Mask value for 'and' operation
1067 @param OrMask Mask value for 'or' operation
1068
1069 @retval EFI_SUCCESS The operation was executed successfully
1070 **/
1071 EFI_STATUS
1072 BootScriptExecuteMemoryReadWrite (
1073 IN UINT8 *Script,
1074 IN UINT64 AndMask,
1075 IN UINT64 OrMask
1076 )
1077
1078 {
1079 EFI_STATUS Status;
1080 UINT64 Data;
1081 EFI_BOOT_SCRIPT_MEM_READ_WRITE MemReadWrite;
1082
1083 Data = 0;
1084
1085 CopyMem((VOID*)&MemReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_MEM_READ_WRITE));
1086
1087 DEBUG ((EFI_D_INFO, "BootScriptExecuteMemoryReadWrite - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)MemReadWrite.Address, AndMask, OrMask));
1088
1089 Status = ScriptMemoryRead (
1090 (S3_BOOT_SCRIPT_LIB_WIDTH) MemReadWrite.Width,
1091 MemReadWrite.Address,
1092 1,
1093 &Data
1094 );
1095 if (!EFI_ERROR (Status)) {
1096 Data = (Data & AndMask) | OrMask;
1097 Status = ScriptMemoryWrite (
1098 (S3_BOOT_SCRIPT_LIB_WIDTH) MemReadWrite.Width,
1099 MemReadWrite.Address,
1100 1,
1101 &Data
1102 );
1103 }
1104 return Status;
1105 }
1106 /**
1107 Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CFG_READ_WRITE OP code.
1108
1109 @param Script The pointer of typed node in boot script table
1110 @param AndMask Mask value for 'and' operation
1111 @param OrMask Mask value for 'or' operation
1112
1113 @retval EFI_SUCCESS The operation was executed successfully
1114 **/
1115 EFI_STATUS
1116 BootScriptExecutePciCfgReadWrite (
1117 IN UINT8 *Script,
1118 IN UINT64 AndMask,
1119 IN UINT64 OrMask
1120 )
1121
1122 {
1123 EFI_STATUS Status;
1124 UINT64 Data;
1125 EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE PciCfgReadWrite;
1126
1127 Data = 0;
1128
1129 CopyMem((VOID*)&PciCfgReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE));
1130
1131 DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfgReadWrite - 0x%08x, 0x%016lx, 0x%016lx\n", PCI_ADDRESS_ENCODE (PciCfgReadWrite.Address), AndMask, OrMask));
1132
1133 Status = ScriptPciCfgRead (
1134 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgReadWrite.Width,
1135 PciCfgReadWrite.Address,
1136 1,
1137 &Data
1138 );
1139 if (EFI_ERROR (Status)) {
1140 return Status;
1141 }
1142
1143 Data = (Data & AndMask) | OrMask;
1144
1145 Status = ScriptPciCfgWrite (
1146 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgReadWrite.Width,
1147 PciCfgReadWrite.Address,
1148 1,
1149 &Data
1150 );
1151
1152 return Status;
1153 }
1154 /**
1155 Interprete the boot script node with EFI_BOOT_SCRIPT_SMBUS_EXECUTE OP code.
1156
1157 @param Script The pointer of typed node in boot script table
1158
1159 @retval EFI_SUCCESS The operation was executed successfully
1160 @retval EFI_UNSUPPORTED Cannot locate smbus ppi or occur error of script execution
1161 @retval Others Result of script execution
1162 **/
1163 EFI_STATUS
1164 BootScriptExecuteSmbusExecute (
1165 IN UINT8 *Script
1166 )
1167 {
1168 UINTN SmBusAddress;
1169 UINTN DataSize;
1170 EFI_BOOT_SCRIPT_SMBUS_EXECUTE SmbusExecuteEntry;
1171
1172 CopyMem ((VOID*)&SmbusExecuteEntry, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_SMBUS_EXECUTE ));
1173
1174 DEBUG ((EFI_D_INFO, "BootScriptExecuteSmbusExecute - 0x%08x, 0x%08x\n", (UINTN)SmbusExecuteEntry.SmBusAddress, (UINTN)SmbusExecuteEntry.Operation));
1175
1176 SmBusAddress = (UINTN)SmbusExecuteEntry.SmBusAddress;
1177 DataSize = (UINTN) SmbusExecuteEntry.DataSize;
1178 return SmbusExecute (
1179 SmBusAddress,
1180 (EFI_SMBUS_OPERATION) SmbusExecuteEntry.Operation,
1181 &DataSize,
1182 Script + sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE)
1183 );
1184 }
1185 /**
1186 Interprete the boot script node with EFI_BOOT_SCRIPT_STALL OP code.
1187
1188 @param Script The pointer of typed node in boot script table
1189
1190 @retval EFI_SUCCESS The operation was executed successfully
1191 **/
1192 EFI_STATUS
1193 BootScriptExecuteStall (
1194 IN UINT8 *Script
1195 )
1196 {
1197 EFI_BOOT_SCRIPT_STALL Stall;
1198
1199 CopyMem ((VOID*)&Stall, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_STALL));
1200
1201 DEBUG ((EFI_D_INFO, "BootScriptExecuteStall - 0x%08x\n", (UINTN)Stall.Duration));
1202
1203 MicroSecondDelay ((UINTN) Stall.Duration);
1204 return EFI_SUCCESS;
1205 }
1206 /**
1207 Interprete the boot script node with EFI_BOOT_SCRIPT_DISPATCH OP code.
1208
1209 @param Script The pointer of typed node in boot script table
1210 @retval EFI_SUCCESS The operation was executed successfully
1211 **/
1212 EFI_STATUS
1213 BootScriptExecuteDispatch (
1214 IN UINT8 *Script
1215 )
1216 {
1217 EFI_STATUS Status;
1218 DISPATCH_ENTRYPOINT_FUNC EntryFunc;
1219 EFI_BOOT_SCRIPT_DISPATCH ScriptDispatch;
1220
1221 CopyMem ((VOID*)&ScriptDispatch, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_DISPATCH));
1222 EntryFunc = (DISPATCH_ENTRYPOINT_FUNC) (UINTN) (ScriptDispatch.EntryPoint);
1223
1224 DEBUG ((EFI_D_INFO, "BootScriptExecuteDispatch - 0x%08x\n", (UINTN)ScriptDispatch.EntryPoint));
1225
1226 Status = EntryFunc (NULL, NULL);
1227
1228 return Status;
1229 }
1230 /**
1231 Interprete the boot script node with EFI_BOOT_SCRIPT_DISPATCH_2 OP code.
1232
1233 @param Script The pointer of typed node in boot script table
1234 @retval EFI_SUCCESS The operation was executed successfully
1235 **/
1236 EFI_STATUS
1237 BootScriptExecuteDispatch2 (
1238 IN UINT8 *Script
1239 )
1240 {
1241 EFI_STATUS Status;
1242 DISPATCH_ENTRYPOINT_FUNC EntryFunc;
1243 EFI_BOOT_SCRIPT_DISPATCH_2 ScriptDispatch2;
1244
1245 CopyMem ((VOID*)&ScriptDispatch2, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_DISPATCH_2));
1246
1247 DEBUG ((EFI_D_INFO, "BootScriptExecuteDispatch2 - 0x%08x(0x%08x)\n", (UINTN)ScriptDispatch2.EntryPoint, (UINTN)ScriptDispatch2.Context));
1248
1249 EntryFunc = (DISPATCH_ENTRYPOINT_FUNC) (UINTN) (ScriptDispatch2.EntryPoint);
1250
1251 Status = EntryFunc (NULL, (VOID *) (UINTN) ScriptDispatch2.Context);
1252
1253 return Status;
1254 }
1255 /**
1256 Interprete the boot script node with EFI_BOOT_SCRIPT_MEM_POLL OP code.
1257
1258 @param Script The pointer of typed node in boot script table
1259 @param AndMask Mask value for 'and' operation
1260 @param OrMask Mask value for 'or' operation
1261
1262 @retval EFI_DEVICE_ERROR Data polled from memory does not equal to
1263 the epecting data within the Loop Times.
1264 @retval EFI_SUCCESS The operation was executed successfully
1265 **/
1266 EFI_STATUS
1267 BootScriptExecuteMemPoll (
1268 IN UINT8 *Script,
1269 IN UINT64 AndMask,
1270 IN UINT64 OrMask
1271 )
1272 {
1273
1274 UINT64 Data;
1275 UINT64 LoopTimes;
1276 EFI_STATUS Status;
1277 EFI_BOOT_SCRIPT_MEM_POLL MemPoll;
1278
1279 CopyMem ((VOID*)&MemPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_MEM_POLL));
1280
1281 DEBUG ((EFI_D_INFO, "BootScriptExecuteMemPoll - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)MemPoll.Address, AndMask, OrMask));
1282
1283 Data = 0;
1284 Status = ScriptMemoryRead (
1285 (S3_BOOT_SCRIPT_LIB_WIDTH) MemPoll.Width,
1286 MemPoll.Address,
1287 1,
1288 &Data
1289 );
1290 if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1291 return EFI_SUCCESS;
1292 }
1293
1294 for (LoopTimes = 0; LoopTimes < MemPoll.LoopTimes; LoopTimes++) {
1295 NanoSecondDelay ((UINTN)MemPoll.Duration);
1296
1297 Data = 0;
1298 Status = ScriptMemoryRead (
1299 (S3_BOOT_SCRIPT_LIB_WIDTH) MemPoll.Width,
1300 MemPoll.Address,
1301 1,
1302 &Data
1303 );
1304 if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1305 return EFI_SUCCESS;
1306 }
1307 }
1308
1309 if (LoopTimes < MemPoll.LoopTimes) {
1310 return EFI_SUCCESS;
1311 } else {
1312 return EFI_DEVICE_ERROR;
1313 }
1314 }
1315 /**
1316 Execute the boot script to interpret the Store arbitrary information.
1317 This opcode is a no-op on dispatch and is only used for debugging script issues.
1318
1319 @param Script The pointer of node in boot script table
1320
1321 **/
1322 VOID
1323 BootScriptExecuteInformation (
1324 IN UINT8 *Script
1325 )
1326
1327 {
1328 UINT32 Index;
1329 EFI_BOOT_SCRIPT_INFORMATION Information;
1330 UINT8 *InformationData;
1331
1332 CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_INFORMATION));
1333
1334 InformationData = Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION);
1335 DEBUG ((EFI_D_INFO, "BootScriptExecuteInformation - 0x%08x\n", (UINTN) InformationData));
1336
1337 DEBUG ((EFI_D_INFO, "BootScriptInformation: "));
1338 for (Index = 0; Index < Information.InformationLength; Index++) {
1339 DEBUG ((EFI_D_INFO, "%02x ", InformationData[Index]));
1340 }
1341 DEBUG ((EFI_D_INFO, "\n"));
1342 }
1343
1344 /**
1345 Execute the boot script to interpret the Label information.
1346
1347 @param Script The pointer of node in boot script table
1348
1349 **/
1350 VOID
1351 BootScriptExecuteLabel (
1352 IN UINT8 *Script
1353 )
1354
1355 {
1356 UINT32 Index;
1357 EFI_BOOT_SCRIPT_INFORMATION Information;
1358 UINT8 *InformationData;
1359
1360 CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_INFORMATION));
1361
1362 InformationData = Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION);
1363 DEBUG ((EFI_D_INFO, "BootScriptExecuteLabel - 0x%08x\n", (UINTN) InformationData));
1364
1365 DEBUG ((EFI_D_INFO, "BootScriptLabel: "));
1366 for (Index = 0; Index < Information.InformationLength; Index++) {
1367 DEBUG ((EFI_D_INFO, "%02x ", InformationData[Index]));
1368 }
1369 DEBUG ((EFI_D_INFO, "\n"));
1370 }
1371
1372 /**
1373 calculate the mask value for 'and' and 'or' operation
1374 @param ScriptHeader The pointer of header of node in boot script table
1375 @param AndMask The Mask value for 'and' operation
1376 @param OrMask The Mask value for 'or' operation
1377 @param Script Pointer to the entry.
1378
1379 **/
1380 VOID
1381 CheckAndOrMask (
1382 IN EFI_BOOT_SCRIPT_COMMON_HEADER *ScriptHeader,
1383 OUT UINT64 *AndMask,
1384 OUT UINT64 *OrMask,
1385 IN UINT8 *Script
1386 )
1387 {
1388 UINT8 *DataPtr;
1389 UINTN Size;
1390
1391 switch (ScriptHeader->OpCode) {
1392 case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
1393 Size = sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE);
1394 break;
1395
1396 case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
1397 Size = sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE);
1398 break;
1399
1400 case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
1401 Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE);
1402 break;
1403 case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
1404 Size = sizeof (EFI_BOOT_SCRIPT_MEM_POLL);
1405 break;
1406
1407 case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
1408 Size = sizeof (EFI_BOOT_SCRIPT_IO_POLL);
1409 break;
1410
1411 case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
1412 Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE);
1413 break;
1414
1415 case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
1416 Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL);
1417 break;
1418
1419 case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
1420 Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL);
1421 break;
1422
1423 default:
1424 return;
1425 }
1426
1427 DataPtr = Script + Size;
1428
1429 switch (ScriptHeader->Width) {
1430 case S3BootScriptWidthUint8:
1431 *AndMask = (UINT64) *(DataPtr + 1);
1432 *OrMask = (UINT64) (*DataPtr);
1433 break;
1434
1435 case S3BootScriptWidthUint16:
1436 *AndMask = (UINT64) (*(UINT16 *) (DataPtr + 2));
1437 *OrMask = (UINT64) (*(UINT16 *) DataPtr);
1438 break;
1439
1440 case S3BootScriptWidthUint32:
1441 *AndMask = (UINT64) (*(UINT32 *) (DataPtr + 4));
1442 *OrMask = (UINT64) (*(UINT32 *) DataPtr);
1443 break;
1444
1445 case S3BootScriptWidthUint64:
1446 *AndMask = (UINT64) (*(UINT64 *) (DataPtr + 8));
1447 *OrMask = (UINT64) (*(UINT64 *) DataPtr);
1448 break;
1449
1450 default:
1451 break;
1452 }
1453
1454 return;
1455 }
1456 /**
1457 Interprete the boot script node with EFI_BOOT_SCRIPT_IO_POLL OP code.
1458
1459 @param Script The pointer of typed node in boot script table
1460 @param AndMask Mask value for 'and' operation
1461 @param OrMask Mask value for 'or' operation
1462
1463 @retval EFI_DEVICE_ERROR Data polled from memory does not equal to
1464 the epecting data within the Loop Times.
1465 @retval EFI_SUCCESS The operation was executed successfully
1466 **/
1467 EFI_STATUS
1468 BootScriptExecuteIoPoll (
1469 IN UINT8 *Script,
1470 IN UINT64 AndMask,
1471 IN UINT64 OrMask
1472 )
1473 {
1474 EFI_STATUS Status;
1475 UINT64 Data;
1476 UINT64 LoopTimes;
1477 EFI_BOOT_SCRIPT_IO_POLL IoPoll;
1478
1479 CopyMem ((VOID*)&IoPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_IO_POLL));
1480
1481 DEBUG ((EFI_D_INFO, "BootScriptExecuteIoPoll - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)IoPoll.Address, AndMask, OrMask));
1482
1483 Data = 0;
1484 Status = ScriptIoRead (
1485 (S3_BOOT_SCRIPT_LIB_WIDTH) IoPoll.Width,
1486 IoPoll.Address,
1487 1,
1488 &Data
1489 );
1490 if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1491 return EFI_SUCCESS;
1492 }
1493 for (LoopTimes = 0; LoopTimes < IoPoll.Delay; LoopTimes++) {
1494 NanoSecondDelay (100);
1495 Data = 0;
1496 Status = ScriptIoRead (
1497 (S3_BOOT_SCRIPT_LIB_WIDTH) IoPoll.Width,
1498 IoPoll.Address,
1499 1,
1500 &Data
1501 );
1502 if ((!EFI_ERROR (Status)) &&(Data & AndMask) == OrMask) {
1503 return EFI_SUCCESS;
1504 }
1505 }
1506
1507 if (LoopTimes < IoPoll.Delay) {
1508 return EFI_SUCCESS;
1509 } else {
1510 return EFI_DEVICE_ERROR;
1511 }
1512 }
1513 /**
1514 Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE OP code.
1515
1516 @param Script The pointer of S3 boot script
1517
1518 @retval EFI_SUCCESS The operation was executed successfully
1519
1520 **/
1521 EFI_STATUS
1522 BootScriptExecutePciCfg2Write (
1523 IN UINT8 *Script
1524 )
1525 {
1526 VOID *Buffer;
1527 S3_BOOT_SCRIPT_LIB_WIDTH Width;
1528 UINT16 Segment;
1529 UINT64 Address;
1530 UINTN Count;
1531 EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE PciCfg2Write;
1532
1533 CopyMem ((VOID*)&PciCfg2Write, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE));
1534
1535 Width = (S3_BOOT_SCRIPT_LIB_WIDTH)PciCfg2Write.Width;
1536 Segment = PciCfg2Write.Segment;
1537 Address = PciCfg2Write.Address;
1538 Count = PciCfg2Write.Count;
1539 Buffer = Script + sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE);
1540
1541 DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfg2Write - 0x%04x, 0x%08x, 0x%08x, 0x%08x\n", Segment, PCI_ADDRESS_ENCODE (Address), Count, (UINTN)Width));
1542 return ScriptPciCfg2Write (Width, Segment, Address, Count, Buffer);
1543 }
1544
1545
1546 /**
1547 Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE OP code.
1548
1549 @param Script The pointer of S3 boot script
1550 @param AndMask Mask value for 'and' operation
1551 @param OrMask Mask value for 'or' operation
1552
1553 @retval EFI_SUCCESS The operation was executed successfully
1554
1555 **/
1556 EFI_STATUS
1557 BootScriptExecutePciCfg2ReadWrite (
1558 IN UINT8 *Script,
1559 IN UINT64 AndMask,
1560 IN UINT64 OrMask
1561 )
1562 {
1563 UINT64 Data;
1564 EFI_STATUS Status;
1565 EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE PciCfg2ReadWrite;
1566
1567 Data = 0;
1568
1569 CopyMem ((VOID*)&PciCfg2ReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE));
1570
1571 DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfg2ReadWrite - 0x%04x, 0x%08x, 0x%016lx, 0x%016lx\n", PciCfg2ReadWrite.Segment, PCI_ADDRESS_ENCODE (PciCfg2ReadWrite.Address), AndMask, OrMask));
1572
1573 Status = ScriptPciCfg2Read (
1574 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2ReadWrite.Width,
1575 PciCfg2ReadWrite.Segment,
1576 PciCfg2ReadWrite.Address,
1577 1,
1578 &Data
1579 );
1580 if (EFI_ERROR (Status)) {
1581 return Status;
1582 }
1583
1584 Data = (Data & AndMask) | OrMask;
1585 Status = ScriptPciCfg2Write (
1586 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2ReadWrite.Width,
1587 PciCfg2ReadWrite.Segment,
1588 PciCfg2ReadWrite.Address,
1589 1,
1590 &Data
1591 );
1592 return Status;
1593 }
1594 /**
1595 Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG_POLL OP code.
1596
1597 @param Script The pointer of S3 boot script
1598 @param AndMask Mask value for 'and' operation
1599 @param OrMask Mask value for 'or' operation
1600
1601 @retval EFI_SUCCESS The operation was executed successfully
1602 @retval EFI_DEVICE_ERROR Data polled from Pci configuration space does not equal to
1603 epecting data within the Loop Times.
1604 **/
1605 EFI_STATUS
1606 BootScriptPciCfgPoll (
1607 IN UINT8 *Script,
1608 IN UINT64 AndMask,
1609 IN UINT64 OrMask
1610 )
1611 {
1612 UINT64 Data;
1613 UINT64 LoopTimes;
1614 EFI_STATUS Status;
1615 EFI_BOOT_SCRIPT_PCI_CONFIG_POLL PciCfgPoll;
1616 CopyMem ((VOID*)&PciCfgPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_POLL));
1617
1618 DEBUG ((EFI_D_INFO, "BootScriptPciCfgPoll - 0x%08x, 0x%016lx, 0x%016lx\n", PCI_ADDRESS_ENCODE (PciCfgPoll.Address), AndMask, OrMask));
1619
1620 Data = 0;
1621 Status = ScriptPciCfgRead (
1622 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgPoll.Width,
1623 PciCfgPoll.Address,
1624 1,
1625 &Data
1626 );
1627 if ((!EFI_ERROR (Status)) &&(Data & AndMask) == OrMask) {
1628 return EFI_SUCCESS;
1629 }
1630
1631 for (LoopTimes = 0; LoopTimes < PciCfgPoll.Delay; LoopTimes++) {
1632 NanoSecondDelay (100);
1633 Data = 0;
1634 Status = ScriptPciCfgRead (
1635 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgPoll.Width,
1636 PciCfgPoll.Address,
1637 1,
1638 &Data
1639 );
1640 if ((!EFI_ERROR (Status)) &&
1641 (Data & AndMask) == OrMask) {
1642 return EFI_SUCCESS;
1643 }
1644 }
1645
1646 if (LoopTimes < PciCfgPoll.Delay) {
1647 return EFI_SUCCESS;
1648 } else {
1649 return EFI_DEVICE_ERROR;
1650 }
1651 }
1652
1653 /**
1654 Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL OP code.
1655
1656 @param Script The pointer of S3 Boot Script
1657 @param AndMask Mask value for 'and' operation
1658 @param OrMask Mask value for 'or' operation
1659
1660 @retval EFI_SUCCESS The operation was executed successfully
1661 @retval EFI_DEVICE_ERROR Data polled from Pci configuration space does not equal to
1662 epecting data within the Loop Times.
1663
1664 **/
1665 EFI_STATUS
1666 BootScriptPciCfg2Poll (
1667 IN UINT8 *Script,
1668 IN UINT64 AndMask,
1669 IN UINT64 OrMask
1670 )
1671 {
1672 EFI_STATUS Status;
1673 UINT64 Data;
1674 UINT64 LoopTimes;
1675 EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL PciCfg2Poll;
1676
1677 Data = 0;
1678 CopyMem ((VOID*)&PciCfg2Poll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL));
1679
1680 DEBUG ((EFI_D_INFO, "BootScriptPciCfg2Poll - 0x%04x, 0x%08x, 0x%016lx, 0x%016lx\n", PciCfg2Poll.Segment, PCI_ADDRESS_ENCODE (PciCfg2Poll.Address), AndMask, OrMask));
1681
1682 Status = ScriptPciCfg2Read (
1683 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2Poll.Width,
1684 PciCfg2Poll.Segment,
1685 PciCfg2Poll.Address,
1686 1,
1687 &Data
1688 );
1689 if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1690 return EFI_SUCCESS;
1691 }
1692
1693 for (LoopTimes = 0; LoopTimes < PciCfg2Poll.Delay; LoopTimes++) {
1694 NanoSecondDelay (100);
1695
1696 Data = 0;
1697 Status = ScriptPciCfg2Read (
1698 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2Poll.Width,
1699 PciCfg2Poll.Segment,
1700 PciCfg2Poll.Address,
1701 1,
1702 &Data
1703 );
1704 if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1705 return EFI_SUCCESS;
1706 }
1707 }
1708
1709 if (LoopTimes < PciCfg2Poll.Delay) {
1710 return EFI_SUCCESS;
1711 } else {
1712 return EFI_DEVICE_ERROR;
1713 }
1714
1715 }
1716
1717 /**
1718 Executes the S3 boot script table.
1719
1720 @retval RETURN_SUCCESS The boot script table was executed successfully.
1721 @retval RETURN_UNSUPPORTED Invalid script table or opcode.
1722
1723 @note A known Limitations in the implementation: When interpreting the opcode EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE
1724 EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE and EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE, the 'Segment' parameter is assumed as
1725 Zero, or else, assert.
1726 **/
1727 RETURN_STATUS
1728 EFIAPI
1729 S3BootScriptExecute (
1730 VOID
1731 )
1732 {
1733 EFI_STATUS Status;
1734 UINT8* Script;
1735 UINTN StartAddress;
1736 UINT32 TableLength;
1737 UINT64 AndMask;
1738 UINT64 OrMask;
1739 EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader;
1740 EFI_BOOT_SCRIPT_TABLE_HEADER TableHeader;
1741 Script = mS3BootScriptTablePtr->TableBase;
1742 if (Script != 0) {
1743 CopyMem ((VOID*)&TableHeader, Script, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));
1744 } else {
1745 return EFI_INVALID_PARAMETER;
1746 }
1747
1748 DEBUG ((EFI_D_INFO, "S3BootScriptExecute:\n"));
1749 if (TableHeader.OpCode != S3_BOOT_SCRIPT_LIB_TABLE_OPCODE) {
1750 return EFI_UNSUPPORTED;
1751 }
1752
1753 DEBUG ((EFI_D_INFO, "TableHeader - 0x%08x\n", Script));
1754
1755 StartAddress = (UINTN) Script;
1756 TableLength = TableHeader.TableLength;
1757 Script = Script + TableHeader.Length;
1758 Status = EFI_SUCCESS;
1759 AndMask = 0;
1760 OrMask = 0;
1761
1762 DEBUG ((EFI_D_INFO, "TableHeader.TableLength - 0x%08x\n", (UINTN)TableLength));
1763
1764 while ((UINTN) Script < (UINTN) (StartAddress + TableLength)) {
1765 DEBUG ((EFI_D_INFO, "ExecuteBootScript - %08x\n", (UINTN)Script));
1766
1767 CopyMem ((VOID*)&ScriptHeader, Script, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER));
1768 switch (ScriptHeader.OpCode) {
1769
1770 case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
1771 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE\n"));
1772 Status = BootScriptExecuteMemoryWrite (Script);
1773 break;
1774
1775 case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
1776 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE\n"));
1777 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1778 Status = BootScriptExecuteMemoryReadWrite (
1779 Script,
1780 AndMask,
1781 OrMask
1782 );
1783 break;
1784
1785 case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
1786 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_WRITE_OPCODE\n"));
1787 Status = BootScriptExecuteIoWrite (Script);
1788 break;
1789
1790 case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
1791 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE\n"));
1792 Status = BootScriptExecutePciCfgWrite (Script);
1793 break;
1794
1795 case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
1796 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE\n"));
1797 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1798 Status = BootScriptExecutePciCfgReadWrite (
1799 Script,
1800 AndMask,
1801 OrMask
1802 );
1803 break;
1804 case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE:
1805 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE\n"));
1806 Status = BootScriptExecutePciCfg2Write (Script);
1807 break;
1808
1809 case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
1810 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE\n"));
1811 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1812 Status = BootScriptExecutePciCfg2ReadWrite (
1813 Script,
1814 AndMask,
1815 OrMask
1816 );
1817 break;
1818 case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:
1819 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_DISPATCH_OPCODE\n"));
1820 Status = BootScriptExecuteDispatch (Script);
1821 break;
1822
1823 case EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE:
1824 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE\n"));
1825 Status = BootScriptExecuteDispatch2 (Script);
1826 break;
1827
1828 case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
1829 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_INFORMATION_OPCODE\n"));
1830 BootScriptExecuteInformation (Script);
1831 break;
1832
1833 case S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE:
1834 DEBUG ((EFI_D_INFO, "S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE\n"));
1835 DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", EFI_SUCCESS));
1836 return EFI_SUCCESS;
1837
1838 case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
1839 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE\n"));
1840 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1841 Status = BootScriptExecuteIoReadWrite (
1842 Script,
1843 AndMask,
1844 OrMask
1845 );
1846 break;
1847
1848 case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE:
1849 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE\n"));
1850 Status = BootScriptExecuteSmbusExecute (Script);
1851 break;
1852
1853 case EFI_BOOT_SCRIPT_STALL_OPCODE:
1854 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_STALL_OPCODE\n"));
1855 Status = BootScriptExecuteStall (Script);
1856 break;
1857
1858 case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
1859 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_POLL_OPCODE\n"));
1860 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1861 Status = BootScriptExecuteMemPoll (Script, AndMask, OrMask);
1862
1863 break;
1864
1865 case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
1866 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_POLL_OPCODE\n"));
1867 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1868 Status = BootScriptExecuteIoPoll (Script, AndMask, OrMask);
1869 break;
1870
1871 case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
1872 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE\n"));
1873 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1874 Status = BootScriptPciCfgPoll (Script, AndMask, OrMask);
1875 break;
1876
1877 case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
1878 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE\n"));
1879 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1880 Status = BootScriptPciCfg2Poll (Script, AndMask, OrMask);
1881 break;
1882
1883 case S3_BOOT_SCRIPT_LIB_LABEL_OPCODE:
1884 //
1885 // For label
1886 //
1887 DEBUG ((EFI_D_INFO, "S3_BOOT_SCRIPT_LIB_LABEL_OPCODE\n"));
1888 BootScriptExecuteLabel (Script);
1889 break;
1890 default:
1891 DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", EFI_UNSUPPORTED));
1892 return EFI_UNSUPPORTED;
1893 }
1894
1895 if (EFI_ERROR (Status)) {
1896 DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", Status));
1897 return Status;
1898 }
1899
1900 Script = Script + ScriptHeader.Length;
1901 }
1902
1903 DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", Status));
1904
1905 return Status;
1906 }
1907