]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c
1. Update IoRead to support UINT64 also.
[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 CopyMem((VOID*)&PciCfgReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE));
1128
1129 DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfgReadWrite - 0x%08x, 0x%016lx, 0x%016lx\n", PCI_ADDRESS_ENCODE (PciCfgReadWrite.Address), AndMask, OrMask));
1130
1131 Status = ScriptPciCfgRead (
1132 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgReadWrite.Width,
1133 PciCfgReadWrite.Address,
1134 1,
1135 &Data
1136 );
1137 if (EFI_ERROR (Status)) {
1138 return Status;
1139 }
1140
1141 Data = (Data & AndMask) | OrMask;
1142
1143 Status = ScriptPciCfgWrite (
1144 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgReadWrite.Width,
1145 PciCfgReadWrite.Address,
1146 1,
1147 &Data
1148 );
1149
1150 return Status;
1151 }
1152 /**
1153 Interprete the boot script node with EFI_BOOT_SCRIPT_SMBUS_EXECUTE OP code.
1154
1155 @param Script The pointer of typed node in boot script table
1156
1157 @retval EFI_SUCCESS The operation was executed successfully
1158 @retval EFI_UNSUPPORTED Cannot locate smbus ppi or occur error of script execution
1159 @retval Others Result of script execution
1160 **/
1161 EFI_STATUS
1162 BootScriptExecuteSmbusExecute (
1163 IN UINT8 *Script
1164 )
1165 {
1166 UINTN SmBusAddress;
1167 UINTN DataSize;
1168 EFI_BOOT_SCRIPT_SMBUS_EXECUTE SmbusExecuteEntry;
1169
1170 CopyMem ((VOID*)&SmbusExecuteEntry, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_SMBUS_EXECUTE ));
1171
1172 DEBUG ((EFI_D_INFO, "BootScriptExecuteSmbusExecute - 0x%08x, 0x%08x\n", (UINTN)SmbusExecuteEntry.SmBusAddress, (UINTN)SmbusExecuteEntry.Operation));
1173
1174 SmBusAddress = (UINTN)SmbusExecuteEntry.SmBusAddress;
1175 DataSize = (UINTN) SmbusExecuteEntry.DataSize;
1176 return SmbusExecute (
1177 SmBusAddress,
1178 (EFI_SMBUS_OPERATION) SmbusExecuteEntry.Operation,
1179 &DataSize,
1180 Script + sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE)
1181 );
1182 }
1183 /**
1184 Interprete the boot script node with EFI_BOOT_SCRIPT_STALL OP code.
1185
1186 @param Script The pointer of typed node in boot script table
1187
1188 @retval EFI_SUCCESS The operation was executed successfully
1189 **/
1190 EFI_STATUS
1191 BootScriptExecuteStall (
1192 IN UINT8 *Script
1193 )
1194 {
1195 EFI_BOOT_SCRIPT_STALL Stall;
1196
1197 CopyMem ((VOID*)&Stall, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_STALL));
1198
1199 DEBUG ((EFI_D_INFO, "BootScriptExecuteStall - 0x%08x\n", (UINTN)Stall.Duration));
1200
1201 MicroSecondDelay ((UINTN) Stall.Duration);
1202 return EFI_SUCCESS;
1203 }
1204 /**
1205 Interprete the boot script node with EFI_BOOT_SCRIPT_DISPATCH OP code.
1206
1207 @param Script The pointer of typed node in boot script table
1208 @retval EFI_SUCCESS The operation was executed successfully
1209 **/
1210 EFI_STATUS
1211 BootScriptExecuteDispatch (
1212 IN UINT8 *Script
1213 )
1214 {
1215 EFI_STATUS Status;
1216 DISPATCH_ENTRYPOINT_FUNC EntryFunc;
1217 EFI_BOOT_SCRIPT_DISPATCH ScriptDispatch;
1218
1219 CopyMem ((VOID*)&ScriptDispatch, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_DISPATCH));
1220 EntryFunc = (DISPATCH_ENTRYPOINT_FUNC) (UINTN) (ScriptDispatch.EntryPoint);
1221
1222 DEBUG ((EFI_D_INFO, "BootScriptExecuteDispatch - 0x%08x\n", (UINTN)ScriptDispatch.EntryPoint));
1223
1224 Status = EntryFunc (NULL, NULL);
1225
1226 return Status;
1227 }
1228 /**
1229 Interprete the boot script node with EFI_BOOT_SCRIPT_DISPATCH_2 OP code.
1230
1231 @param Script The pointer of typed node in boot script table
1232 @retval EFI_SUCCESS The operation was executed successfully
1233 **/
1234 EFI_STATUS
1235 BootScriptExecuteDispatch2 (
1236 IN UINT8 *Script
1237 )
1238 {
1239 EFI_STATUS Status;
1240 DISPATCH_ENTRYPOINT_FUNC EntryFunc;
1241 EFI_BOOT_SCRIPT_DISPATCH_2 ScriptDispatch2;
1242
1243 CopyMem ((VOID*)&ScriptDispatch2, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_DISPATCH_2));
1244
1245 DEBUG ((EFI_D_INFO, "BootScriptExecuteDispatch2 - 0x%08x(0x%08x)\n", (UINTN)ScriptDispatch2.EntryPoint, (UINTN)ScriptDispatch2.Context));
1246
1247 EntryFunc = (DISPATCH_ENTRYPOINT_FUNC) (UINTN) (ScriptDispatch2.EntryPoint);
1248
1249 Status = EntryFunc (NULL, (VOID *) (UINTN) ScriptDispatch2.Context);
1250
1251 return Status;
1252 }
1253 /**
1254 Interprete the boot script node with EFI_BOOT_SCRIPT_MEM_POLL OP code.
1255
1256 @param Script The pointer of typed node in boot script table
1257 @param AndMask Mask value for 'and' operation
1258 @param OrMask Mask value for 'or' operation
1259
1260 @retval EFI_DEVICE_ERROR Data polled from memory does not equal to
1261 the epecting data within the Loop Times.
1262 @retval EFI_SUCCESS The operation was executed successfully
1263 **/
1264 EFI_STATUS
1265 BootScriptExecuteMemPoll (
1266 IN UINT8 *Script,
1267 IN UINT64 AndMask,
1268 IN UINT64 OrMask
1269 )
1270 {
1271
1272 UINT64 Data;
1273 UINT64 LoopTimes;
1274 EFI_STATUS Status;
1275 EFI_BOOT_SCRIPT_MEM_POLL MemPoll;
1276
1277 CopyMem ((VOID*)&MemPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_MEM_POLL));
1278
1279 DEBUG ((EFI_D_INFO, "BootScriptExecuteMemPoll - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)MemPoll.Address, AndMask, OrMask));
1280
1281 Data = 0;
1282 Status = ScriptMemoryRead (
1283 (S3_BOOT_SCRIPT_LIB_WIDTH) MemPoll.Width,
1284 MemPoll.Address,
1285 1,
1286 &Data
1287 );
1288 if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1289 return EFI_SUCCESS;
1290 }
1291
1292 for (LoopTimes = 0; LoopTimes < MemPoll.LoopTimes; LoopTimes++) {
1293 NanoSecondDelay ((UINTN)MemPoll.Duration);
1294
1295 Data = 0;
1296 Status = ScriptMemoryRead (
1297 (S3_BOOT_SCRIPT_LIB_WIDTH) MemPoll.Width,
1298 MemPoll.Address,
1299 1,
1300 &Data
1301 );
1302 if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1303 return EFI_SUCCESS;
1304 }
1305 }
1306
1307 if (LoopTimes < MemPoll.LoopTimes) {
1308 return EFI_SUCCESS;
1309 } else {
1310 return EFI_DEVICE_ERROR;
1311 }
1312 }
1313 /**
1314 Execute the boot script to interpret the Store arbitrary information.
1315 This opcode is a no-op on dispatch and is only used for debugging script issues.
1316
1317 @param Script The pointer of node in boot script table
1318
1319 **/
1320 VOID
1321 BootScriptExecuteInformation (
1322 IN UINT8 *Script
1323 )
1324
1325 {
1326 UINT32 Index;
1327 EFI_BOOT_SCRIPT_INFORMATION Information;
1328 UINT8 *InformationData;
1329
1330 CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_INFORMATION));
1331
1332 InformationData = Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION);
1333 DEBUG ((EFI_D_INFO, "BootScriptExecuteInformation - 0x%08x\n", (UINTN) InformationData));
1334
1335 DEBUG ((EFI_D_INFO, "BootScriptInformation: "));
1336 for (Index = 0; Index < Information.InformationLength; Index++) {
1337 DEBUG ((EFI_D_INFO, "%02x ", InformationData[Index]));
1338 }
1339 DEBUG ((EFI_D_INFO, "\n"));
1340 }
1341
1342 /**
1343 Execute the boot script to interpret the Label information.
1344
1345 @param Script The pointer of node in boot script table
1346
1347 **/
1348 VOID
1349 BootScriptExecuteLabel (
1350 IN UINT8 *Script
1351 )
1352
1353 {
1354 UINT32 Index;
1355 EFI_BOOT_SCRIPT_INFORMATION Information;
1356 UINT8 *InformationData;
1357
1358 CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_INFORMATION));
1359
1360 InformationData = Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION);
1361 DEBUG ((EFI_D_INFO, "BootScriptExecuteLabel - 0x%08x\n", (UINTN) InformationData));
1362
1363 DEBUG ((EFI_D_INFO, "BootScriptLabel: "));
1364 for (Index = 0; Index < Information.InformationLength; Index++) {
1365 DEBUG ((EFI_D_INFO, "%02x ", InformationData[Index]));
1366 }
1367 DEBUG ((EFI_D_INFO, "\n"));
1368 }
1369
1370 /**
1371 calculate the mask value for 'and' and 'or' operation
1372 @param ScriptHeader The pointer of header of node in boot script table
1373 @param AndMask The Mask value for 'and' operation
1374 @param OrMask The Mask value for 'or' operation
1375 @param Script Pointer to the entry.
1376
1377 **/
1378 VOID
1379 CheckAndOrMask (
1380 IN EFI_BOOT_SCRIPT_COMMON_HEADER *ScriptHeader,
1381 OUT UINT64 *AndMask,
1382 OUT UINT64 *OrMask,
1383 IN UINT8 *Script
1384 )
1385 {
1386 UINT8 *DataPtr;
1387 UINTN Size;
1388
1389 switch (ScriptHeader->OpCode) {
1390 case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
1391 Size = sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE);
1392 break;
1393
1394 case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
1395 Size = sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE);
1396 break;
1397
1398 case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
1399 Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE);
1400 break;
1401 case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
1402 Size = sizeof (EFI_BOOT_SCRIPT_MEM_POLL);
1403 break;
1404
1405 case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
1406 Size = sizeof (EFI_BOOT_SCRIPT_IO_POLL);
1407 break;
1408
1409 case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
1410 Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE);
1411 break;
1412
1413 case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
1414 Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL);
1415 break;
1416
1417 case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
1418 Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL);
1419 break;
1420
1421 default:
1422 return;
1423 }
1424
1425 DataPtr = Script + Size;
1426
1427 switch (ScriptHeader->Width) {
1428 case S3BootScriptWidthUint8:
1429 *AndMask = (UINT64) *(DataPtr + 1);
1430 *OrMask = (UINT64) (*DataPtr);
1431 break;
1432
1433 case S3BootScriptWidthUint16:
1434 *AndMask = (UINT64) (*(UINT16 *) (DataPtr + 2));
1435 *OrMask = (UINT64) (*(UINT16 *) DataPtr);
1436 break;
1437
1438 case S3BootScriptWidthUint32:
1439 *AndMask = (UINT64) (*(UINT32 *) (DataPtr + 4));
1440 *OrMask = (UINT64) (*(UINT32 *) DataPtr);
1441 break;
1442
1443 case S3BootScriptWidthUint64:
1444 *AndMask = (UINT64) (*(UINT64 *) (DataPtr + 8));
1445 *OrMask = (UINT64) (*(UINT64 *) DataPtr);
1446 break;
1447
1448 default:
1449 break;
1450 }
1451
1452 return;
1453 }
1454 /**
1455 Interprete the boot script node with EFI_BOOT_SCRIPT_IO_POLL OP code.
1456
1457 @param Script The pointer of typed node in boot script table
1458 @param AndMask Mask value for 'and' operation
1459 @param OrMask Mask value for 'or' operation
1460
1461 @retval EFI_DEVICE_ERROR Data polled from memory does not equal to
1462 the epecting data within the Loop Times.
1463 @retval EFI_SUCCESS The operation was executed successfully
1464 **/
1465 EFI_STATUS
1466 BootScriptExecuteIoPoll (
1467 IN UINT8 *Script,
1468 IN UINT64 AndMask,
1469 IN UINT64 OrMask
1470 )
1471 {
1472 EFI_STATUS Status;
1473 UINT64 Data;
1474 UINT64 LoopTimes;
1475 EFI_BOOT_SCRIPT_IO_POLL IoPoll;
1476
1477 CopyMem ((VOID*)&IoPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_IO_POLL));
1478
1479 DEBUG ((EFI_D_INFO, "BootScriptExecuteIoPoll - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)IoPoll.Address, AndMask, OrMask));
1480
1481 Data = 0;
1482 Status = ScriptIoRead (
1483 (S3_BOOT_SCRIPT_LIB_WIDTH) IoPoll.Width,
1484 IoPoll.Address,
1485 1,
1486 &Data
1487 );
1488 if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1489 return EFI_SUCCESS;
1490 }
1491 for (LoopTimes = 0; LoopTimes < IoPoll.Delay; LoopTimes++) {
1492 NanoSecondDelay (100);
1493 Data = 0;
1494 Status = ScriptIoRead (
1495 (S3_BOOT_SCRIPT_LIB_WIDTH) IoPoll.Width,
1496 IoPoll.Address,
1497 1,
1498 &Data
1499 );
1500 if ((!EFI_ERROR (Status)) &&(Data & AndMask) == OrMask) {
1501 return EFI_SUCCESS;
1502 }
1503 }
1504
1505 if (LoopTimes < IoPoll.Delay) {
1506 return EFI_SUCCESS;
1507 } else {
1508 return EFI_DEVICE_ERROR;
1509 }
1510 }
1511 /**
1512 Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE OP code.
1513
1514 @param Script The pointer of S3 boot script
1515
1516 @retval EFI_SUCCESS The operation was executed successfully
1517
1518 **/
1519 EFI_STATUS
1520 BootScriptExecutePciCfg2Write (
1521 IN UINT8 *Script
1522 )
1523 {
1524 VOID *Buffer;
1525 S3_BOOT_SCRIPT_LIB_WIDTH Width;
1526 UINT16 Segment;
1527 UINT64 Address;
1528 UINTN Count;
1529 EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE PciCfg2Write;
1530
1531 CopyMem ((VOID*)&PciCfg2Write, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE));
1532
1533 Width = (S3_BOOT_SCRIPT_LIB_WIDTH)PciCfg2Write.Width;
1534 Segment = PciCfg2Write.Segment;
1535 Address = PciCfg2Write.Address;
1536 Count = PciCfg2Write.Count;
1537 Buffer = Script + sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE);
1538
1539 DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfg2Write - 0x%04x, 0x%08x, 0x%08x, 0x%08x\n", Segment, PCI_ADDRESS_ENCODE (Address), Count, (UINTN)Width));
1540 return ScriptPciCfg2Write (Width, Segment, Address, Count, Buffer);
1541 }
1542
1543
1544 /**
1545 Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE OP code.
1546
1547 @param Script The pointer of S3 boot script
1548 @param AndMask Mask value for 'and' operation
1549 @param OrMask Mask value for 'or' operation
1550
1551 @retval EFI_SUCCESS The operation was executed successfully
1552
1553 **/
1554 EFI_STATUS
1555 BootScriptExecutePciCfg2ReadWrite (
1556 IN UINT8 *Script,
1557 IN UINT64 AndMask,
1558 IN UINT64 OrMask
1559 )
1560 {
1561 UINT64 Data;
1562 EFI_STATUS Status;
1563 EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE PciCfg2ReadWrite;
1564 CopyMem ((VOID*)&PciCfg2ReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE));
1565
1566 DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfg2ReadWrite - 0x%04x, 0x%08x, 0x%016lx, 0x%016lx\n", PciCfg2ReadWrite.Segment, PCI_ADDRESS_ENCODE (PciCfg2ReadWrite.Address), AndMask, OrMask));
1567
1568 Status = ScriptPciCfg2Read (
1569 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2ReadWrite.Width,
1570 PciCfg2ReadWrite.Segment,
1571 PciCfg2ReadWrite.Address,
1572 1,
1573 &Data
1574 );
1575 if (EFI_ERROR (Status)) {
1576 return Status;
1577 }
1578
1579 Data = (Data & AndMask) | OrMask;
1580 Status = ScriptPciCfg2Write (
1581 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2ReadWrite.Width,
1582 PciCfg2ReadWrite.Segment,
1583 PciCfg2ReadWrite.Address,
1584 1,
1585 &Data
1586 );
1587 return Status;
1588 }
1589 /**
1590 Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG_POLL OP code.
1591
1592 @param Script The pointer of S3 boot script
1593 @param AndMask Mask value for 'and' operation
1594 @param OrMask Mask value for 'or' operation
1595
1596 @retval EFI_SUCCESS The operation was executed successfully
1597 @retval EFI_DEVICE_ERROR Data polled from Pci configuration space does not equal to
1598 epecting data within the Loop Times.
1599 **/
1600 EFI_STATUS
1601 BootScriptPciCfgPoll (
1602 IN UINT8 *Script,
1603 IN UINT64 AndMask,
1604 IN UINT64 OrMask
1605 )
1606 {
1607 UINT64 Data;
1608 UINT64 LoopTimes;
1609 EFI_STATUS Status;
1610 EFI_BOOT_SCRIPT_PCI_CONFIG_POLL PciCfgPoll;
1611 CopyMem ((VOID*)&PciCfgPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_POLL));
1612
1613 DEBUG ((EFI_D_INFO, "BootScriptPciCfgPoll - 0x%08x, 0x%016lx, 0x%016lx\n", PCI_ADDRESS_ENCODE (PciCfgPoll.Address), AndMask, OrMask));
1614
1615 Data = 0;
1616 Status = ScriptPciCfgRead (
1617 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgPoll.Width,
1618 PciCfgPoll.Address,
1619 1,
1620 &Data
1621 );
1622 if ((!EFI_ERROR (Status)) &&(Data & AndMask) == OrMask) {
1623 return EFI_SUCCESS;
1624 }
1625
1626 for (LoopTimes = 0; LoopTimes < PciCfgPoll.Delay; LoopTimes++) {
1627 NanoSecondDelay (100);
1628 Data = 0;
1629 Status = ScriptPciCfgRead (
1630 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgPoll.Width,
1631 PciCfgPoll.Address,
1632 1,
1633 &Data
1634 );
1635 if ((!EFI_ERROR (Status)) &&
1636 (Data & AndMask) == OrMask) {
1637 return EFI_SUCCESS;
1638 }
1639 }
1640
1641 if (LoopTimes < PciCfgPoll.Delay) {
1642 return EFI_SUCCESS;
1643 } else {
1644 return EFI_DEVICE_ERROR;
1645 }
1646 }
1647
1648 /**
1649 Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL OP code.
1650
1651 @param Script The pointer of S3 Boot Script
1652 @param AndMask Mask value for 'and' operation
1653 @param OrMask Mask value for 'or' operation
1654
1655 @retval EFI_SUCCESS The operation was executed successfully
1656 @retval EFI_DEVICE_ERROR Data polled from Pci configuration space does not equal to
1657 epecting data within the Loop Times.
1658
1659 **/
1660 EFI_STATUS
1661 BootScriptPciCfg2Poll (
1662 IN UINT8 *Script,
1663 IN UINT64 AndMask,
1664 IN UINT64 OrMask
1665 )
1666 {
1667 EFI_STATUS Status;
1668 UINT64 Data;
1669 UINT64 LoopTimes;
1670 EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL PciCfg2Poll;
1671
1672 Data = 0;
1673 CopyMem ((VOID*)&PciCfg2Poll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL));
1674
1675 DEBUG ((EFI_D_INFO, "BootScriptPciCfg2Poll - 0x%04x, 0x%08x, 0x%016lx, 0x%016lx\n", PciCfg2Poll.Segment, PCI_ADDRESS_ENCODE (PciCfg2Poll.Address), AndMask, OrMask));
1676
1677 Status = ScriptPciCfg2Read (
1678 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2Poll.Width,
1679 PciCfg2Poll.Segment,
1680 PciCfg2Poll.Address,
1681 1,
1682 &Data
1683 );
1684 if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1685 return EFI_SUCCESS;
1686 }
1687
1688 for (LoopTimes = 0; LoopTimes < PciCfg2Poll.Delay; LoopTimes++) {
1689 NanoSecondDelay (100);
1690
1691 Data = 0;
1692 Status = ScriptPciCfg2Read (
1693 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2Poll.Width,
1694 PciCfg2Poll.Segment,
1695 PciCfg2Poll.Address,
1696 1,
1697 &Data
1698 );
1699 if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1700 return EFI_SUCCESS;
1701 }
1702 }
1703
1704 if (LoopTimes < PciCfg2Poll.Delay) {
1705 return EFI_SUCCESS;
1706 } else {
1707 return EFI_DEVICE_ERROR;
1708 }
1709
1710 }
1711
1712 /**
1713 Executes the S3 boot script table.
1714
1715 @retval RETURN_SUCCESS The boot script table was executed successfully.
1716 @retval RETURN_UNSUPPORTED Invalid script table or opcode.
1717
1718 @note A known Limitations in the implementation: When interpreting the opcode EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE
1719 EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE and EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE, the 'Segment' parameter is assumed as
1720 Zero, or else, assert.
1721 **/
1722 RETURN_STATUS
1723 EFIAPI
1724 S3BootScriptExecute (
1725 VOID
1726 )
1727 {
1728 EFI_STATUS Status;
1729 UINT8* Script;
1730 UINTN StartAddress;
1731 UINT32 TableLength;
1732 UINT64 AndMask;
1733 UINT64 OrMask;
1734 EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader;
1735 EFI_BOOT_SCRIPT_TABLE_HEADER TableHeader;
1736 Script = mS3BootScriptTablePtr->TableBase;
1737 if (Script != 0) {
1738 CopyMem ((VOID*)&TableHeader, Script, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));
1739 } else {
1740 return EFI_INVALID_PARAMETER;
1741 }
1742
1743 DEBUG ((EFI_D_INFO, "S3BootScriptExecute:\n"));
1744 if (TableHeader.OpCode != S3_BOOT_SCRIPT_LIB_TABLE_OPCODE) {
1745 return EFI_UNSUPPORTED;
1746 }
1747
1748 DEBUG ((EFI_D_INFO, "TableHeader - 0x%08x\n", Script));
1749
1750 StartAddress = (UINTN) Script;
1751 TableLength = TableHeader.TableLength;
1752 Script = Script + TableHeader.Length;
1753 Status = EFI_SUCCESS;
1754 AndMask = 0;
1755 OrMask = 0;
1756
1757 DEBUG ((EFI_D_INFO, "TableHeader.TableLength - 0x%08x\n", (UINTN)TableLength));
1758
1759 while ((UINTN) Script < (UINTN) (StartAddress + TableLength)) {
1760 DEBUG ((EFI_D_INFO, "ExecuteBootScript - %08x\n", (UINTN)Script));
1761
1762 CopyMem ((VOID*)&ScriptHeader, Script, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER));
1763 switch (ScriptHeader.OpCode) {
1764
1765 case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
1766 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE\n"));
1767 Status = BootScriptExecuteMemoryWrite (Script);
1768 break;
1769
1770 case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
1771 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE\n"));
1772 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1773 Status = BootScriptExecuteMemoryReadWrite (
1774 Script,
1775 AndMask,
1776 OrMask
1777 );
1778 break;
1779
1780 case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
1781 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_WRITE_OPCODE\n"));
1782 Status = BootScriptExecuteIoWrite (Script);
1783 break;
1784
1785 case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
1786 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE\n"));
1787 Status = BootScriptExecutePciCfgWrite (Script);
1788 break;
1789
1790 case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
1791 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE\n"));
1792 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1793 Status = BootScriptExecutePciCfgReadWrite (
1794 Script,
1795 AndMask,
1796 OrMask
1797 );
1798 break;
1799 case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE:
1800 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE\n"));
1801 Status = BootScriptExecutePciCfg2Write (Script);
1802 break;
1803
1804 case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
1805 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE\n"));
1806 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1807 Status = BootScriptExecutePciCfg2ReadWrite (
1808 Script,
1809 AndMask,
1810 OrMask
1811 );
1812 break;
1813 case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:
1814 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_DISPATCH_OPCODE\n"));
1815 Status = BootScriptExecuteDispatch (Script);
1816 break;
1817
1818 case EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE:
1819 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE\n"));
1820 Status = BootScriptExecuteDispatch2 (Script);
1821 break;
1822
1823 case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
1824 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_INFORMATION_OPCODE\n"));
1825 BootScriptExecuteInformation (Script);
1826 break;
1827
1828 case S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE:
1829 DEBUG ((EFI_D_INFO, "S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE\n"));
1830 DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", EFI_SUCCESS));
1831 return EFI_SUCCESS;
1832
1833 case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
1834 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE\n"));
1835 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1836 Status = BootScriptExecuteIoReadWrite (
1837 Script,
1838 AndMask,
1839 OrMask
1840 );
1841 break;
1842
1843 case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE:
1844 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE\n"));
1845 Status = BootScriptExecuteSmbusExecute (Script);
1846 break;
1847
1848 case EFI_BOOT_SCRIPT_STALL_OPCODE:
1849 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_STALL_OPCODE\n"));
1850 Status = BootScriptExecuteStall (Script);
1851 break;
1852
1853 case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
1854 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_POLL_OPCODE\n"));
1855 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1856 Status = BootScriptExecuteMemPoll (Script, AndMask, OrMask);
1857
1858 break;
1859
1860 case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
1861 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_POLL_OPCODE\n"));
1862 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1863 Status = BootScriptExecuteIoPoll (Script, AndMask, OrMask);
1864 break;
1865
1866 case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
1867 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE\n"));
1868 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1869 Status = BootScriptPciCfgPoll (Script, AndMask, OrMask);
1870 break;
1871
1872 case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
1873 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE\n"));
1874 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1875 Status = BootScriptPciCfg2Poll (Script, AndMask, OrMask);
1876 break;
1877
1878 case S3_BOOT_SCRIPT_LIB_LABEL_OPCODE:
1879 //
1880 // For label
1881 //
1882 DEBUG ((EFI_D_INFO, "S3_BOOT_SCRIPT_LIB_LABEL_OPCODE\n"));
1883 BootScriptExecuteLabel (Script);
1884 break;
1885 default:
1886 DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", EFI_UNSUPPORTED));
1887 return EFI_UNSUPPORTED;
1888 }
1889
1890 if (EFI_ERROR (Status)) {
1891 DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", Status));
1892 return Status;
1893 }
1894
1895 Script = Script + ScriptHeader.Length;
1896 }
1897
1898 DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", Status));
1899
1900 return Status;
1901 }
1902