]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c
Use mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE) to get...
[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 Translates boot script to MDE library interface.
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 case S3BootScriptWidthFifoUint8:
335 case S3BootScriptWidthFillUint8:
336 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8Read - 0x%08x\n", Address));
337 *Out.Uint8 = IoRead8 ((UINTN) Address);
338 break;
339
340 case S3BootScriptWidthUint16:
341 case S3BootScriptWidthFifoUint16:
342 case S3BootScriptWidthFillUint16:
343 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16Read - 0x%08x\n", Address));
344 *Out.Uint16 = IoRead16 ((UINTN) Address);
345 break;
346
347 case S3BootScriptWidthUint32:
348 case S3BootScriptWidthFifoUint32:
349 case S3BootScriptWidthFillUint32:
350 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32Read - 0x%08x\n", Address));
351 *Out.Uint32 = IoRead32 ((UINTN) Address);
352 break;
353
354 default:
355 return EFI_INVALID_PARAMETER;
356 }
357 }
358
359 return EFI_SUCCESS;
360 }
361
362 /**
363 Perform a write operation
364
365 @param[in] Width Width of the operation.
366 @param[in] Address Address of the operation.
367 @param[in] Count Count of the number of accesses to perform.
368 @param[in] Buffer Pointer to the buffer to write to I/O space.
369
370 @retval EFI_SUCCESS The data was written to the EFI System.
371 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
372 Buffer is NULL.
373 The Buffer is not aligned for the given Width.
374 Address is outside the legal range of I/O ports.
375
376 **/
377 EFI_STATUS
378 ScriptIoWrite (
379 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
380 IN UINT64 Address,
381 IN UINTN Count,
382 IN VOID *Buffer
383 )
384 {
385 EFI_STATUS Status;
386 UINTN AddressStride;
387 UINTN BufferStride;
388 UINT64 OriginalAddress;
389 PTR In;
390 PTR OriginalIn;
391
392 In.Buf = (UINT8 *) Buffer;
393
394 if (Address > MAX_IO_ADDRESS) {
395 return EFI_INVALID_PARAMETER;
396 }
397
398 Status = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
399 if (EFI_ERROR (Status)) {
400 return Status;
401 }
402 //
403 // Loop for each iteration and move the data
404 //
405 OriginalAddress = Address;
406 OriginalIn.Buf = In.Buf;
407 for (; Count > 0; Count--, Address += AddressStride, In.Buf += BufferStride) {
408 switch (Width) {
409 case S3BootScriptWidthUint8:
410 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*In.Uint8));
411 IoWrite8 ((UINTN) Address, *In.Uint8);
412 break;
413 case S3BootScriptWidthFifoUint8:
414 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x (0x%02x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint8));
415 IoWrite8 ((UINTN) OriginalAddress, *In.Uint8);
416 break;
417 case S3BootScriptWidthFillUint8:
418 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint8));
419 IoWrite8 ((UINTN) Address, *OriginalIn.Uint8);
420 break;
421 case S3BootScriptWidthUint16:
422 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*In.Uint16));
423 IoWrite16 ((UINTN) Address, *In.Uint16);
424 break;
425 case S3BootScriptWidthFifoUint16:
426 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x (0x%04x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint16));
427 IoWrite16 ((UINTN) OriginalAddress, *In.Uint16);
428 break;
429 case S3BootScriptWidthFillUint16:
430 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint16));
431 IoWrite16 ((UINTN) Address, *OriginalIn.Uint16);
432 break;
433 case S3BootScriptWidthUint32:
434 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*In.Uint32));
435 IoWrite32 ((UINTN) Address, *In.Uint32);
436 break;
437 case S3BootScriptWidthFifoUint32:
438 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x (0x%08x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint32));
439 IoWrite32 ((UINTN) OriginalAddress, *In.Uint32);
440 break;
441 case S3BootScriptWidthFillUint32:
442 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint32));
443 IoWrite32 ((UINTN) Address, *OriginalIn.Uint32);
444 break;
445 case S3BootScriptWidthUint64:
446 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *In.Uint64));
447 IoWrite64 ((UINTN) Address, *In.Uint64);
448 break;
449 case S3BootScriptWidthFifoUint64:
450 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint64 - 0x%08x (0x%016lx)\n", (UINTN)OriginalAddress, *In.Uint64));
451 IoWrite64 ((UINTN) OriginalAddress, *In.Uint64);
452 break;
453 case S3BootScriptWidthFillUint64:
454 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *OriginalIn.Uint64));
455 IoWrite64 ((UINTN) Address, *OriginalIn.Uint64);
456 break;
457 default:
458 return EFI_INVALID_PARAMETER;
459 }
460 }
461
462
463 return EFI_SUCCESS;
464 }
465 /**
466 Interprete the IO write entry in S3 boot script and perform the write operation
467
468 @param Script Pointer to the node which is to be interpreted.
469
470 @retval EFI_SUCCESS The data was written to the EFI System.
471 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
472 Buffer is NULL.
473 The Buffer is not aligned for the given Width.
474 Address is outside the legal range of I/O ports.
475
476 **/
477 EFI_STATUS
478 BootScriptExecuteIoWrite (
479 IN UINT8 *Script
480 )
481 {
482 S3_BOOT_SCRIPT_LIB_WIDTH Width;
483 UINT64 Address;
484 UINTN Count;
485 VOID *Buffer;
486 EFI_BOOT_SCRIPT_IO_WRITE IoWrite;
487
488 CopyMem ((VOID*)&IoWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_IO_WRITE));
489 Width = (S3_BOOT_SCRIPT_LIB_WIDTH) IoWrite.Width;
490 Address = IoWrite.Address;
491 Count = IoWrite.Count;
492 Buffer = Script + sizeof (EFI_BOOT_SCRIPT_IO_WRITE);
493
494 return ScriptIoWrite(Width, Address, Count, Buffer);
495 }
496 /**
497 Perform memory read operation
498
499 @param Width Width of the operation.
500 @param Address Address of the operation.
501 @param Count Count of the number of accesses to perform.
502 @param Buffer Pointer to the buffer read from memory.
503
504 @retval EFI_SUCCESS The data was written to the EFI System.
505 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
506 Buffer is NULL.
507 The Buffer is not aligned for the given Width.
508 @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count
509 is not valid for this EFI System.
510
511 **/
512 EFI_STATUS
513 ScriptMemoryRead (
514 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
515 IN UINT64 Address,
516 IN UINTN Count,
517 IN OUT VOID *Buffer
518 )
519 {
520 EFI_STATUS Status;
521 UINTN AddressStride;
522 UINTN BufferStride;
523 PTR Out;
524
525 Out.Buf = Buffer;
526
527 Status = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
528 if (EFI_ERROR (Status)) {
529 return Status;
530 }
531 //
532 // Loop for each iteration and move the data
533 //
534 for (; Count > 0; Count--, Address += AddressStride, Out.Buf += BufferStride) {
535 switch (Width) {
536 case S3BootScriptWidthUint8:
537 case S3BootScriptWidthFifoUint8:
538 case S3BootScriptWidthFillUint8:
539 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x\n", (UINTN)Address));
540 *Out.Uint8 = MmioRead8 ((UINTN) Address);
541 break;
542
543 case S3BootScriptWidthUint16:
544 case S3BootScriptWidthFifoUint16:
545 case S3BootScriptWidthFillUint16:
546 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x\n", (UINTN)Address));
547 *Out.Uint16 = MmioRead16 ((UINTN) Address);
548 break;
549
550 case S3BootScriptWidthUint32:
551 case S3BootScriptWidthFifoUint32:
552 case S3BootScriptWidthFillUint32:
553 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x\n", (UINTN)Address));
554 *Out.Uint32 = MmioRead32 ((UINTN) Address);
555 break;
556
557 case S3BootScriptWidthUint64:
558 case S3BootScriptWidthFifoUint64:
559 case S3BootScriptWidthFillUint64:
560 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x\n", (UINTN)Address));
561 *Out.Uint64 = MmioRead64 ((UINTN) Address);
562 break;
563
564 default:
565 return EFI_UNSUPPORTED;
566 }
567 }
568
569 return EFI_SUCCESS;
570 }
571 /**
572 Translates boot script to MDE library interface.
573
574 @param Width Width of the operation.
575 @param Address Address of the operation.
576 @param Count Count of the number of accesses to perform.
577 @param Buffer Pointer to the buffer write to memory.
578
579 @retval EFI_SUCCESS The data was written to the EFI System.
580 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
581 Buffer is NULL.
582 The Buffer is not aligned for the given Width.
583 @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count
584 is not valid for this EFI System.
585
586 **/
587 EFI_STATUS
588 ScriptMemoryWrite (
589 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
590 IN UINT64 Address,
591 IN UINTN Count,
592 IN OUT VOID *Buffer
593 )
594 {
595 EFI_STATUS Status;
596 UINTN AddressStride;
597 UINT64 OriginalAddress;
598 UINTN BufferStride;
599 PTR In;
600 PTR OriginalIn;
601
602 In.Buf = Buffer;
603
604 Status = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
605 if (EFI_ERROR (Status)) {
606 return Status;
607 }
608 //
609 // Loop for each iteration and move the data
610 //
611 OriginalAddress = Address;
612 OriginalIn.Buf = In.Buf;
613 for (; Count > 0; Count--, Address += AddressStride, In.Buf += BufferStride) {
614 switch (Width) {
615 case S3BootScriptWidthUint8:
616 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*In.Uint8));
617 MmioWrite8 ((UINTN) Address, *In.Uint8);
618 break;
619 case S3BootScriptWidthFifoUint8:
620 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x (0x%02x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint8));
621 MmioWrite8 ((UINTN) OriginalAddress, *In.Uint8);
622 break;
623 case S3BootScriptWidthFillUint8:
624 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint8));
625 MmioWrite8 ((UINTN) Address, *OriginalIn.Uint8);
626 break;
627 case S3BootScriptWidthUint16:
628 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*In.Uint16));
629 MmioWrite16 ((UINTN) Address, *In.Uint16);
630 break;
631 case S3BootScriptWidthFifoUint16:
632 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x (0x%04x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint16));
633 MmioWrite16 ((UINTN) OriginalAddress, *In.Uint16);
634 break;
635 case S3BootScriptWidthFillUint16:
636 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint16));
637 MmioWrite16 ((UINTN) Address, *OriginalIn.Uint16);
638 break;
639 case S3BootScriptWidthUint32:
640 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*In.Uint32));
641 MmioWrite32 ((UINTN) Address, *In.Uint32);
642 break;
643 case S3BootScriptWidthFifoUint32:
644 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x (0x%08x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint32));
645 MmioWrite32 ((UINTN) OriginalAddress, *In.Uint32);
646 break;
647 case S3BootScriptWidthFillUint32:
648 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint32));
649 MmioWrite32 ((UINTN) Address, *OriginalIn.Uint32);
650 break;
651 case S3BootScriptWidthUint64:
652 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *In.Uint64));
653 MmioWrite64 ((UINTN) Address, *In.Uint64);
654 break;
655 case S3BootScriptWidthFifoUint64:
656 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint64 - 0x%08x (0x%016lx)\n", (UINTN)OriginalAddress, *In.Uint64));
657 MmioWrite64 ((UINTN) OriginalAddress, *In.Uint64);
658 break;
659 case S3BootScriptWidthFillUint64:
660 DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *OriginalIn.Uint64));
661 MmioWrite64 ((UINTN) Address, *OriginalIn.Uint64);
662 break;
663 default:
664 return EFI_UNSUPPORTED;
665 }
666 }
667 return EFI_SUCCESS;
668 }
669 /**
670 Interprete the boot script node with EFI_BOOT_SCRIPT_MEM_WRITE OP code.
671
672 @param[in] Script Pointer to the node which is to be interpreted.
673
674 @retval EFI_SUCCESS The data was written to the EFI System.
675 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
676 Buffer is NULL.
677 The Buffer is not aligned for the given Width.
678 @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count
679 is not valid for this EFI System.
680
681 **/
682 EFI_STATUS
683 BootScriptExecuteMemoryWrite (
684 IN UINT8 *Script
685 )
686 {
687 VOID *Buffer;
688 S3_BOOT_SCRIPT_LIB_WIDTH Width;
689 UINT64 Address;
690 UINTN Count;
691 EFI_BOOT_SCRIPT_MEM_WRITE MemWrite;
692
693 CopyMem((VOID*)&MemWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_MEM_WRITE));
694 Width = (S3_BOOT_SCRIPT_LIB_WIDTH)MemWrite.Width;
695 Address = MemWrite.Address;
696 Count = MemWrite.Count;
697 Buffer = Script + sizeof(EFI_BOOT_SCRIPT_MEM_WRITE);
698
699 DEBUG ((EFI_D_INFO, "BootScriptExecuteMemoryWrite - 0x%08x, 0x%08x, 0x%08x\n", (UINTN)Address, (UINTN)Count, (UINTN)Width));
700 return ScriptMemoryWrite (Width,Address, Count, Buffer);
701
702 }
703 /**
704 Translates boot script to MDE library interface for PCI configuration read operation
705
706 @param Width Width of the operation.
707 @param Address Address of the operation.
708 @param Buffer Pointer to the buffer reaf from PCI config space
709
710 @retval EFI_SUCCESS The read succeed.
711 @retval EFI_INVALID_PARAMETER if Width is not defined
712
713 **/
714 EFI_STATUS
715 ScriptPciCfgRead (
716 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
717 IN UINT64 Address,
718 OUT VOID *Buffer
719 )
720 {
721 switch (Width) {
722 case S3BootScriptWidthUint8:
723 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%016lx\n", Address));
724 * (UINT8 *) Buffer = PciRead8 (PCI_ADDRESS_ENCODE(Address));
725 break;
726
727 case S3BootScriptWidthUint16:
728 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%016lx\n", Address));
729 * (UINT16 *) Buffer = PciRead16 (PCI_ADDRESS_ENCODE(Address));
730 break;
731
732 case S3BootScriptWidthUint32:
733 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%016lx\n", Address));
734 * (UINT32 *) Buffer = PciRead32 (PCI_ADDRESS_ENCODE(Address));
735 break;
736
737 default:
738 return EFI_INVALID_PARAMETER;
739 }
740 return EFI_SUCCESS;
741 }
742
743 /**
744 Translates boot script to MDE library interface for PCI configuration write operation
745
746 @param Width Width of the operation.
747 @param Address Address of the operation.
748 @param Buffer Pointer to the buffer reaf from PCI config space
749
750 @retval EFI_SUCCESS The write succeed.
751 @retval EFI_INVALID_PARAMETER if Width is not defined
752
753 **/
754 EFI_STATUS
755 ScriptPciCfgWrite (
756 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
757 IN UINT64 Address,
758 OUT VOID *Buffer
759 )
760 {
761 switch (Width) {
762 case S3BootScriptWidthUint8:
763 case S3BootScriptWidthFifoUint8:
764 case S3BootScriptWidthFillUint8:
765 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%016lx (0x%02x)\n", Address, (UINTN)*(UINT8 *) Buffer));
766 PciWrite8 (PCI_ADDRESS_ENCODE(Address), *(UINT8 *) Buffer);
767 break;
768 case S3BootScriptWidthUint16:
769 case S3BootScriptWidthFifoUint16:
770 case S3BootScriptWidthFillUint16:
771 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%016lx (0x%04x)\n", Address, (UINTN)*(UINT16 *) Buffer));
772 PciWrite16 (PCI_ADDRESS_ENCODE(Address), *(UINT16 *) Buffer);
773 break;
774 case S3BootScriptWidthUint32:
775 case S3BootScriptWidthFifoUint32:
776 case S3BootScriptWidthFillUint32:
777 DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%016lx (0x%08x)\n", Address, (UINTN)*(UINT32 *) Buffer));
778 PciWrite32 (PCI_ADDRESS_ENCODE(Address), *(UINT32 *) Buffer);
779 break;
780 default:
781 return EFI_INVALID_PARAMETER;
782 }
783 return EFI_SUCCESS;
784 }
785 /**
786 Perform pci configure 2 read operation.
787
788 @param Width Width of the operation.
789 @param Segment Pci segment number
790 @param Address Address of the operation.
791 @param Buffer Pointer to the buffer to write to I/O space.
792
793 @retval EFI_SUCCESS The data was written to the EFI System.
794 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
795 Buffer is NULL.
796 The Buffer is not aligned for the given Width.
797 Address is outside the legal range of I/O ports.
798 @note A known Limitations in the implementation which is the 'Segment' parameter is assumed as
799 Zero, or else, assert.
800 **/
801 EFI_STATUS
802 ScriptPciCfg2Read (
803 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
804 IN UINT16 Segment,
805 IN UINT64 Address,
806 OUT VOID *Buffer
807 )
808 {
809 ASSERT (Segment==0);
810
811 return ScriptPciCfgRead (Width, Address, Buffer);
812 }
813 /**
814 Perform pci configure write operation.
815
816 @param Width Width of the operation.
817 @param Segment Pci segment number
818 @param Address Address of the operation.
819 @param Buffer Pointer to the buffer to write to I/O space.
820
821 @retval EFI_SUCCESS The data was written to the EFI System.
822 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
823 Buffer is NULL.
824 The Buffer is not aligned for the given Width.
825 Address is outside the legal range of I/O ports.
826 @note A known Limitations in the implementation which is the 'Segment' parameter is assumed as
827 Zero, or else, assert.
828
829 **/
830 EFI_STATUS
831 EFIAPI
832 ScriptPciCfg2Write (
833 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
834 IN UINT16 Segment,
835 IN UINT64 Address,
836 OUT VOID *Buffer
837 )
838 {
839 ASSERT (Segment==0);
840 return ScriptPciCfgWrite (Width, Address, Buffer);
841 }
842 /**
843 Perform Pci configuration Write operation.
844
845 @param Script The pointer of typed node in boot script table
846
847 @retval EFI_SUCCESS The operation was executed successfully
848 **/
849 EFI_STATUS
850 BootScriptExecutePciCfgWrite (
851 IN UINT8 *Script
852 )
853 {
854 EFI_STATUS Status;
855 UINT8 *Buffer;
856 UINTN DataWidth;
857 UINTN Index;
858 UINT64 PciAddress;
859 UINT8 Reg;
860 EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE PciConfigWrite;
861
862 CopyMem ((VOID*)&PciConfigWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE));
863 Status = EFI_SUCCESS;
864
865 PciAddress = PciConfigWrite.Address;
866 DataWidth = (UINT32)(0x01 << (PciConfigWrite.Width));
867 Buffer = Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE);
868
869 DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfgWrite - 0x%08x, 0x%08x, 0x%08x\n", (UINTN)PciAddress, (UINTN)PciConfigWrite.Count, (UINTN)DataWidth));
870
871 for (Index = 0; Index < PciConfigWrite.Count; Index++) {
872 Status = ScriptPciCfgWrite (
873 (S3_BOOT_SCRIPT_LIB_WIDTH) PciConfigWrite.Width,
874 PciAddress,
875 Buffer
876 );
877
878 if ( S3BootScriptWidthFillUint8 != PciConfigWrite.Width ||
879 S3BootScriptWidthFillUint16 != PciConfigWrite.Width ||
880 S3BootScriptWidthFillUint32 != PciConfigWrite.Width ||
881 S3BootScriptWidthFillUint64 != PciConfigWrite.Width){
882 Reg = (UINT8) ((UINT8) PciAddress + DataWidth);
883 PciAddress = (PciAddress & 0xFFFFFFFFFFFFFF00ULL) + Reg;
884 }
885
886 if (S3BootScriptWidthFifoUint8 != PciConfigWrite.Width ||
887 S3BootScriptWidthFifoUint16 != PciConfigWrite.Width ||
888 S3BootScriptWidthFifoUint32 != PciConfigWrite.Width ||
889 S3BootScriptWidthFifoUint64 != PciConfigWrite.Width) {
890 Buffer += DataWidth;
891 }
892 }
893
894 return Status;
895 }
896 /**
897 Excute the script to perform IO modification operation.
898
899 @param Script The pointer of typed node in boot script table
900 @param AndMask Mask value for 'and' operation
901 @param OrMask Mask value for 'or' operation
902
903 @retval EFI_SUCCESS The operation was executed successfully
904 **/
905 EFI_STATUS
906 BootScriptExecuteIoReadWrite (
907 IN UINT8 *Script,
908 IN UINT64 AndMask,
909 IN UINT64 OrMask
910 )
911
912 {
913 EFI_STATUS Status;
914 UINT64 Data;
915 EFI_BOOT_SCRIPT_IO_READ_WRITE IoReadWrite;
916
917 Data = 0;
918
919 CopyMem((VOID*)&IoReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_IO_READ_WRITE));
920
921 DEBUG ((EFI_D_INFO, "BootScriptExecuteIoReadWrite - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)IoReadWrite.Address, (UINT64)AndMask, (UINT64)OrMask));
922
923 Status = ScriptIoRead (
924 (S3_BOOT_SCRIPT_LIB_WIDTH) IoReadWrite.Width,
925 IoReadWrite.Address,
926 1,
927 &Data
928 );
929 if (!EFI_ERROR (Status)) {
930 Data = (Data & AndMask) | OrMask;
931 Status = ScriptIoWrite (
932 (S3_BOOT_SCRIPT_LIB_WIDTH) IoReadWrite.Width,
933 IoReadWrite.Address,
934 1,
935 &Data
936 );
937 }
938 return Status;
939 }
940 /**
941 Excute the script to perform memory modification operation.
942
943 @param Script The pointer of typed node in boot script table
944 @param AndMask Mask value for 'and' operation
945 @param OrMask Mask value for 'or' operation
946
947 @retval EFI_SUCCESS The operation was executed successfully
948 **/
949 EFI_STATUS
950 BootScriptExecuteMemoryReadWrite (
951 IN UINT8 *Script,
952 IN UINT64 AndMask,
953 IN UINT64 OrMask
954 )
955
956 {
957 EFI_STATUS Status;
958 UINT64 Data;
959 EFI_BOOT_SCRIPT_MEM_READ_WRITE MemReadWrite;
960
961 Data = 0;
962
963 CopyMem((VOID*)&MemReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_MEM_READ_WRITE));
964
965 DEBUG ((EFI_D_INFO, "BootScriptExecuteMemoryReadWrite - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)MemReadWrite.Address, (UINT64)AndMask, (UINT64)OrMask));
966
967 Status = ScriptMemoryRead (
968 (S3_BOOT_SCRIPT_LIB_WIDTH) MemReadWrite.Width,
969 MemReadWrite.Address,
970 1,
971 &Data
972 );
973 if (!EFI_ERROR (Status)) {
974 Data = (Data & AndMask) | OrMask;
975 Status = ScriptMemoryWrite (
976 (S3_BOOT_SCRIPT_LIB_WIDTH) MemReadWrite.Width,
977 MemReadWrite.Address,
978 1,
979 &Data
980 );
981 }
982 return Status;
983 }
984 /**
985 Excute the script to perform PCI IO modification operation.
986
987 @param Script The pointer of typed node in boot script table
988 @param AndMask Mask value for 'and' operation
989 @param OrMask Mask value for 'or' operation
990
991 @retval EFI_SUCCESS The operation was executed successfully
992 **/
993 EFI_STATUS
994 BootScriptExecutePciCfgReadWrite (
995 IN UINT8 *Script,
996 IN UINT64 AndMask,
997 IN UINT64 OrMask
998 )
999
1000 {
1001 EFI_STATUS Status;
1002 UINT64 Data;
1003 EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE PciCfgReadWrite;
1004
1005 CopyMem((VOID*)&PciCfgReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE));
1006
1007 DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfgReadWrite - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)PciCfgReadWrite.Address, (UINT64)AndMask, (UINT64)OrMask));
1008
1009 Status = ScriptPciCfgRead (
1010 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgReadWrite.Width,
1011 PciCfgReadWrite.Address,
1012 &Data
1013 );
1014 if (EFI_ERROR (Status)) {
1015 return Status;
1016 }
1017
1018 Data = (Data & AndMask) | OrMask;
1019
1020 Status = ScriptPciCfgWrite (
1021 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgReadWrite.Width,
1022 PciCfgReadWrite.Address,
1023 &Data
1024 );
1025
1026 return Status;
1027 }
1028 /**
1029 To Execute SMBUS command.
1030
1031 @param Script The pointer of typed node in boot script table
1032
1033 @retval EFI_SUCCESS The operation was executed successfully
1034 @retval EFI_UNSUPPORTED Cannot locate smbus ppi or occur error of script execution
1035 @retval Others Result of script execution
1036 **/
1037 EFI_STATUS
1038 BootScriptExecuteSmbusExecute (
1039 IN UINT8 *Script
1040 )
1041 {
1042 UINTN SmBusAddress;
1043 UINTN DataSize;
1044 EFI_BOOT_SCRIPT_SMBUS_EXECUTE SmbusExecuteEntry;
1045
1046 CopyMem ((VOID*)&SmbusExecuteEntry, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_SMBUS_EXECUTE ));
1047
1048 DEBUG ((EFI_D_INFO, "BootScriptExecuteSmbusExecute - 0x%08x, 0x%08x\n", (UINTN)SmbusExecuteEntry.SmBusAddress, (UINTN)SmbusExecuteEntry.Operation));
1049
1050 SmBusAddress = (UINTN)SmbusExecuteEntry.SmBusAddress;
1051 DataSize = (UINTN) SmbusExecuteEntry.DataSize;
1052 return SmbusExecute (
1053 SmBusAddress,
1054 (EFI_SMBUS_OPERATION) SmbusExecuteEntry.Operation,
1055 &DataSize,
1056 Script + sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE)
1057 );
1058 }
1059 /**
1060 Execute stall operation in boot script table.
1061
1062 @param Script The pointer of typed node in boot script table
1063
1064 @retval EFI_SUCCESS The operation was executed successfully
1065 **/
1066 EFI_STATUS
1067 BootScriptExecuteStall (
1068 IN UINT8 *Script
1069 )
1070 {
1071 EFI_BOOT_SCRIPT_STALL Stall;
1072
1073 CopyMem ((VOID*)&Stall, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_STALL));
1074
1075 DEBUG ((EFI_D_INFO, "BootScriptExecuteStall - 0x%08x\n", (UINTN)Stall.Duration));
1076
1077 MicroSecondDelay ((UINTN) Stall.Duration);
1078 return EFI_SUCCESS;
1079 }
1080 /**
1081 To execute assigned function.
1082
1083 @param Script The pointer of typed node in boot script table
1084 @retval EFI_SUCCESS The operation was executed successfully
1085 **/
1086 EFI_STATUS
1087 BootScriptExecuteDispatch (
1088 IN UINT8 *Script
1089 )
1090 {
1091 EFI_STATUS Status;
1092 DISPATCH_ENTRYPOINT_FUNC EntryFunc;
1093 EFI_BOOT_SCRIPT_DISPATCH ScriptDispatch;
1094
1095 CopyMem ((VOID*)&ScriptDispatch, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_DISPATCH));
1096 EntryFunc = (DISPATCH_ENTRYPOINT_FUNC) (UINTN) (ScriptDispatch.EntryPoint);
1097
1098 DEBUG ((EFI_D_INFO, "BootScriptExecuteDispatch - 0x%08x\n", (UINTN)ScriptDispatch.EntryPoint));
1099
1100 Status = EntryFunc (NULL, NULL);
1101
1102 return Status;
1103 }
1104 /**
1105 Execute dispach2 opertion code which is to invoke a spcified function with one parameter.
1106
1107 @param Script The pointer of typed node in boot script table
1108 @retval EFI_SUCCESS The operation was executed successfully
1109 **/
1110 EFI_STATUS
1111 BootScriptExecuteDispatch2 (
1112 IN UINT8 *Script
1113 )
1114 {
1115 EFI_STATUS Status;
1116 DISPATCH_ENTRYPOINT_FUNC EntryFunc;
1117 EFI_BOOT_SCRIPT_DISPATCH_2 ScriptDispatch2;
1118
1119 CopyMem ((VOID*)&ScriptDispatch2, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_DISPATCH_2));
1120
1121 DEBUG ((EFI_D_INFO, "BootScriptExecuteDispatch2 - 0x%08x(0x%08x)\n", (UINTN)ScriptDispatch2.EntryPoint, (UINTN)ScriptDispatch2.Context));
1122
1123 EntryFunc = (DISPATCH_ENTRYPOINT_FUNC) (UINTN) (ScriptDispatch2.EntryPoint);
1124
1125 Status = EntryFunc (NULL, (VOID *) (UINTN) ScriptDispatch2.Context);
1126
1127 return Status;
1128 }
1129 /**
1130 Excute the script to poll memory.
1131
1132 @param Script The pointer of typed node in boot script table
1133 @param AndMask Mask value for 'and' operation
1134 @param OrMask Mask value for 'or' operation
1135
1136 @retval EFI_DEVICE_ERROR Data polled from memory does not equal to
1137 the epecting data within the Loop Times.
1138 @retval EFI_SUCCESS The operation was executed successfully
1139 **/
1140 EFI_STATUS
1141 BootScriptExecuteMemPoll (
1142 IN UINT8 *Script,
1143 IN UINT64 AndMask,
1144 IN UINT64 OrMask
1145 )
1146 {
1147
1148 UINT64 Data;
1149 UINT64 LoopTimes;
1150 EFI_STATUS Status;
1151 EFI_BOOT_SCRIPT_MEM_POLL MemPoll;
1152
1153 CopyMem ((VOID*)&MemPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_MEM_POLL));
1154
1155 DEBUG ((EFI_D_INFO, "BootScriptExecuteMemPoll - 0x%08x\n", (UINTN)MemPoll.Address));
1156
1157 Data = 0;
1158 Status = ScriptMemoryRead (
1159 (S3_BOOT_SCRIPT_LIB_WIDTH) MemPoll.Width,
1160 MemPoll.Address,
1161 1,
1162 &Data
1163 );
1164 if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1165 return EFI_SUCCESS;
1166 }
1167
1168 for (LoopTimes = 0; LoopTimes < MemPoll.LoopTimes; LoopTimes++) {
1169 NanoSecondDelay ((UINTN)MemPoll.Duration);
1170
1171 Data = 0;
1172 Status = ScriptMemoryRead (
1173 (S3_BOOT_SCRIPT_LIB_WIDTH) MemPoll.Width,
1174 MemPoll.Address,
1175 1,
1176 &Data
1177 );
1178 if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1179 return EFI_SUCCESS;
1180 }
1181 }
1182
1183 if (LoopTimes < MemPoll.LoopTimes) {
1184 return EFI_SUCCESS;
1185 } else {
1186 return EFI_DEVICE_ERROR;
1187 }
1188 }
1189 /**
1190 Execute the boot script to interpret the Store arbitrary information.
1191 This opcode is a no-op on dispatch and is only used for debugging script issues.
1192
1193 @param Script The pointer of node in boot script table
1194
1195 **/
1196 VOID
1197 BootScriptExecuteInformation (
1198 IN UINT8 *Script
1199 )
1200
1201 {
1202 UINT32 Index;
1203 EFI_BOOT_SCRIPT_INFORMATION Information;
1204
1205 CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(Information));
1206
1207 DEBUG ((EFI_D_INFO, "BootScriptExecuteInformation - 0x%08x\n", (UINTN)Information.Information));
1208
1209 DEBUG ((EFI_D_INFO, "BootScriptInformation: "));
1210 for (Index = 0; Index < Information.InformationLength; Index++) {
1211 DEBUG ((EFI_D_INFO, "%02x ", *(UINT8 *)(UINTN)(Information.Information + Index)));
1212 }
1213 DEBUG ((EFI_D_INFO, "\n"));
1214 }
1215
1216 /**
1217 Execute the boot script to interpret the Label information.
1218
1219 @param Script The pointer of node in boot script table
1220
1221 **/
1222 VOID
1223 BootScriptExecuteLabel (
1224 IN UINT8 *Script
1225 )
1226
1227 {
1228 UINT32 Index;
1229 EFI_BOOT_SCRIPT_INFORMATION Information;
1230
1231 CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(Information));
1232
1233 DEBUG ((EFI_D_INFO, "BootScriptExecuteLabel - 0x%08x\n", (UINTN)Information.Information));
1234
1235 DEBUG ((EFI_D_INFO, "BootScriptLabel: "));
1236 for (Index = 0; Index < Information.InformationLength; Index++) {
1237 DEBUG ((EFI_D_INFO, "%02x ", *(UINT8 *)(UINTN)(Information.Information + Index)));
1238 }
1239 DEBUG ((EFI_D_INFO, "\n"));
1240 }
1241
1242 /**
1243 calculate the mask value for 'and' and 'or' operation
1244 @param ScriptHeader The pointer of header of node in boot script table
1245 @param AndMask The Mask value for 'and' operation
1246 @param OrMask The Mask value for 'or' operation
1247 @param Script Pointer to the entry.
1248
1249 **/
1250 VOID
1251 CheckAndOrMask (
1252 IN EFI_BOOT_SCRIPT_COMMON_HEADER *ScriptHeader,
1253 OUT UINT64 *AndMask,
1254 OUT UINT64 *OrMask,
1255 IN UINT8 *Script
1256 )
1257 {
1258 UINT8 *DataPtr;
1259 UINTN Size;
1260
1261 switch (ScriptHeader->OpCode) {
1262 case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
1263 Size = sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE);
1264 break;
1265
1266 case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
1267 Size = sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE);
1268 break;
1269
1270 case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
1271 Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE);
1272 break;
1273 case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
1274 Size = sizeof (EFI_BOOT_SCRIPT_MEM_POLL);
1275 break;
1276
1277 case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
1278 Size = sizeof (EFI_BOOT_SCRIPT_IO_POLL);
1279 break;
1280
1281 case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
1282 Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE);
1283 break;
1284
1285 case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
1286 Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL);
1287 break;
1288
1289 case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
1290 Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL);
1291 break;
1292
1293 default:
1294 return;
1295 }
1296
1297 DataPtr = Script + Size;
1298
1299 switch (ScriptHeader->Width) {
1300 case S3BootScriptWidthUint8:
1301 *AndMask = (UINT64) *(DataPtr + 1);
1302 *OrMask = (UINT64) (*DataPtr);
1303 break;
1304
1305 case S3BootScriptWidthUint16:
1306 *AndMask = (UINT64) (*(UINT16 *) (DataPtr + 2));
1307 *OrMask = (UINT64) (*(UINT16 *) DataPtr);
1308 break;
1309
1310 case S3BootScriptWidthUint32:
1311 *AndMask = (UINT64) (*(UINT32 *) (DataPtr + 4));
1312 *OrMask = (UINT64) (*(UINT32 *) DataPtr);
1313 break;
1314
1315 case S3BootScriptWidthUint64:
1316 *AndMask = (UINT64) (*(UINT64 *) (DataPtr + 8));
1317 *OrMask = (UINT64) (*(UINT64 *) DataPtr);
1318 break;
1319
1320 default:
1321 break;
1322 }
1323
1324 return;
1325 }
1326 /**
1327 Excute the script to poll Io port for some time
1328
1329 @param Script The pointer of typed node in boot script table
1330 @param AndMask Mask value for 'and' operation
1331 @param OrMask Mask value for 'or' operation
1332
1333 @retval EFI_DEVICE_ERROR Data polled from memory does not equal to
1334 the epecting data within the Loop Times.
1335 @retval EFI_SUCCESS The operation was executed successfully
1336 **/
1337 EFI_STATUS
1338 BootScriptExecuteIoPoll (
1339 IN UINT8 *Script,
1340 IN UINT64 AndMask,
1341 IN UINT64 OrMask
1342 )
1343 {
1344 EFI_STATUS Status;
1345 UINT64 Data;
1346 UINT64 LoopTimes;
1347 EFI_BOOT_SCRIPT_IO_POLL IoPoll;
1348
1349 CopyMem ((VOID*)&IoPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_IO_POLL));
1350
1351 DEBUG ((EFI_D_INFO, "BootScriptExecuteIoPoll - 0x%08x\n", (UINTN)IoPoll.Address));
1352
1353 Data = 0;
1354 Status = ScriptIoRead (
1355 (S3_BOOT_SCRIPT_LIB_WIDTH) IoPoll.Width,
1356 IoPoll.Address,
1357 1,
1358 &Data
1359 );
1360 if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1361 return EFI_SUCCESS;
1362 }
1363 for (LoopTimes = 0; LoopTimes < IoPoll.Delay; LoopTimes++) {
1364 NanoSecondDelay (100);
1365 Data = 0;
1366 Status = ScriptIoRead (
1367 (S3_BOOT_SCRIPT_LIB_WIDTH) IoPoll.Width,
1368 IoPoll.Address,
1369 1,
1370 &Data
1371 );
1372 if ((!EFI_ERROR (Status)) &&(Data & AndMask) == OrMask) {
1373 return EFI_SUCCESS;
1374 }
1375 }
1376
1377 if (LoopTimes < IoPoll.Delay) {
1378 return EFI_SUCCESS;
1379 } else {
1380 return EFI_DEVICE_ERROR;
1381 }
1382 }
1383 /**
1384 Perform Pci configuration Write operation.
1385
1386 @param Script The pointer of S3 boot script
1387
1388 @retval EFI_SUCCESS The operation was executed successfully
1389
1390 **/
1391 EFI_STATUS
1392 BootScriptExecutePciCfg2Write (
1393 IN UINT8 *Script
1394 )
1395 {
1396 UINT8 Reg;
1397 UINT8 *Buffer;
1398 UINTN DataWidth;
1399 UINTN Index;
1400 UINT16 Segment;
1401 UINT64 PciAddress;
1402 EFI_STATUS Status;
1403 EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE PciCfg2Write;
1404
1405 CopyMem ((VOID*)&PciCfg2Write, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE));
1406 Status = EFI_SUCCESS;
1407 Segment = PciCfg2Write.Segment;
1408 PciAddress = PciCfg2Write.Address;
1409 DataWidth = (UINT32)(0x01 << (PciCfg2Write.Width));
1410 Buffer = Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE);
1411
1412 DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfg2Write - 0x%08x\n", (UINTN)PciAddress));
1413
1414 for (Index = 0; Index < PciCfg2Write.Count; Index++) {
1415 Status = ScriptPciCfg2Write (
1416 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2Write.Width,
1417 Segment,
1418 PciAddress,
1419 Buffer
1420 );
1421 if (S3BootScriptWidthFillUint8 != PciCfg2Write.Width ||
1422 S3BootScriptWidthFillUint16 != PciCfg2Write.Width ||
1423 S3BootScriptWidthFillUint32 != PciCfg2Write.Width ||
1424 S3BootScriptWidthFillUint64 != PciCfg2Write.Width){
1425 Reg = (UINT8) ((UINT8) PciAddress + DataWidth);
1426 PciAddress = (PciAddress & 0xFFFFFFFFFFFFFF00ULL) + Reg;
1427 }
1428
1429 if (S3BootScriptWidthFifoUint8 != PciCfg2Write.Width ||
1430 S3BootScriptWidthFifoUint16 != PciCfg2Write.Width ||
1431 S3BootScriptWidthFifoUint32 != PciCfg2Write.Width ||
1432 S3BootScriptWidthFifoUint64 != PciCfg2Write.Width) {
1433 Buffer += DataWidth;
1434 }
1435 }
1436 return Status;
1437 }
1438
1439
1440 /**
1441 Perform pci configuration read & Write operation.
1442
1443 @param Script The pointer of S3 boot script
1444 @param AndMask Mask value for 'and' operation
1445 @param OrMask Mask value for 'or' operation
1446
1447 @retval EFI_SUCCESS The operation was executed successfully
1448
1449 **/
1450 EFI_STATUS
1451 BootScriptExecutePciCfg2ReadWrite (
1452 IN UINT8 *Script,
1453 IN UINT64 AndMask,
1454 IN UINT64 OrMask
1455 )
1456 {
1457 UINT64 Data;
1458 EFI_STATUS Status;
1459 EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE PciCfg2ReadWrite;
1460 CopyMem ((VOID*)&PciCfg2ReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE));
1461
1462 DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfg2ReadWrite - 0x%08x\n", (UINTN)PciCfg2ReadWrite.Address));
1463
1464 Status = ScriptPciCfg2Read (
1465 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2ReadWrite.Width,
1466 PciCfg2ReadWrite.Segment,
1467 PciCfg2ReadWrite.Address,
1468 &Data
1469 );
1470 if (EFI_ERROR (Status)) {
1471 return Status;
1472 }
1473
1474 Data = (Data & AndMask) | OrMask;
1475 Status = ScriptPciCfg2Write (
1476 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2ReadWrite.Width,
1477 PciCfg2ReadWrite.Segment,
1478 PciCfg2ReadWrite.Address,
1479 &Data
1480 );
1481 return Status;
1482 }
1483 /**
1484 To perform poll pci configure operation.
1485
1486 @param Script The pointer of S3 boot script
1487 @param AndMask Mask value for 'and' operation
1488 @param OrMask Mask value for 'or' operation
1489
1490 @retval EFI_SUCCESS The operation was executed successfully
1491 @retval EFI_DEVICE_ERROR Data polled from Pci configuration space does not equal to
1492 epecting data within the Loop Times.
1493 **/
1494 EFI_STATUS
1495 BootScriptPciCfgPoll (
1496 IN UINT8 *Script,
1497 IN UINT64 AndMask,
1498 IN UINT64 OrMask
1499 )
1500 {
1501 UINT64 Data;
1502 UINT64 LoopTimes;
1503 EFI_STATUS Status;
1504 EFI_BOOT_SCRIPT_PCI_CONFIG_POLL PciCfgPoll;
1505 CopyMem ((VOID*)&PciCfgPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_POLL));
1506
1507 DEBUG ((EFI_D_INFO, "BootScriptPciCfgPoll - 0x%08x\n", (UINTN)PciCfgPoll.Address));
1508
1509 Data = 0;
1510 Status = ScriptPciCfgRead (
1511 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgPoll.Width,
1512 PciCfgPoll.Address,
1513 &Data
1514 );
1515 if ((!EFI_ERROR (Status)) &&(Data & AndMask) == OrMask) {
1516 return EFI_SUCCESS;
1517 }
1518
1519 for (LoopTimes = 0; LoopTimes < PciCfgPoll.Delay; LoopTimes++) {
1520 NanoSecondDelay (100);
1521 Data = 0;
1522 Status = ScriptPciCfgRead (
1523 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgPoll.Width,
1524 PciCfgPoll.Address,
1525 &Data
1526 );
1527 if ((!EFI_ERROR (Status)) &&
1528 (Data & AndMask) == OrMask) {
1529 return EFI_SUCCESS;
1530 }
1531 }
1532
1533 if (LoopTimes < PciCfgPoll.Delay) {
1534 return EFI_SUCCESS;
1535 } else {
1536 return EFI_DEVICE_ERROR;
1537 }
1538 }
1539
1540 /**
1541 To perform poll pci configure operation.
1542
1543 @param Script The pointer of S3 Boot Script
1544 @param AndMask Mask value for 'and' operation
1545 @param OrMask Mask value for 'or' operation
1546
1547 @retval EFI_SUCCESS The operation was executed successfully
1548 @retval EFI_DEVICE_ERROR Data polled from Pci configuration space does not equal to
1549 epecting data within the Loop Times.
1550
1551 **/
1552 EFI_STATUS
1553 BootScriptPciCfg2Poll (
1554 IN UINT8 *Script,
1555 IN UINT64 AndMask,
1556 IN UINT64 OrMask
1557 )
1558 {
1559 EFI_STATUS Status;
1560 UINT64 Data;
1561 UINT64 LoopTimes;
1562 EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL PciCfg2Poll;
1563
1564 Data = 0;
1565 CopyMem ((VOID*)&PciCfg2Poll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL));
1566
1567 DEBUG ((EFI_D_INFO, "BootScriptPciCfg2Poll - 0x%08x\n", (UINTN)PciCfg2Poll.Address));
1568
1569 Status = ScriptPciCfg2Read (
1570 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2Poll.Width,
1571 PciCfg2Poll.Segment,
1572 PciCfg2Poll.Address,
1573 &Data
1574 );
1575 if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1576 return EFI_SUCCESS;
1577 }
1578
1579 for (LoopTimes = 0; LoopTimes < PciCfg2Poll.Delay; LoopTimes++) {
1580 NanoSecondDelay (100);
1581
1582 Data = 0;
1583 Status = ScriptPciCfg2Read (
1584 (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2Poll.Width,
1585 PciCfg2Poll.Segment,
1586 PciCfg2Poll.Address,
1587 &Data
1588 );
1589 if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1590 return EFI_SUCCESS;
1591 }
1592 }
1593
1594 if (LoopTimes < PciCfg2Poll.Delay) {
1595 return EFI_SUCCESS;
1596 } else {
1597 return EFI_DEVICE_ERROR;
1598 }
1599
1600 }
1601
1602 /**
1603 Executes the S3 boot script table.
1604
1605 @retval RETURN_SUCCESS The boot script table was executed successfully.
1606 @retval RETURN_UNSUPPORTED Invalid script table or opcode.
1607
1608 @note A known Limitations in the implementation: When interpreting the opcode EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE
1609 EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE and EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE, the 'Segment' parameter is assumed as
1610 Zero, or else, assert.
1611 **/
1612 RETURN_STATUS
1613 EFIAPI
1614 S3BootScriptExecute (
1615 VOID
1616 )
1617 {
1618 EFI_STATUS Status;
1619 UINT8* Script;
1620 UINTN StartAddress;
1621 UINT32 TableLength;
1622 UINT64 AndMask;
1623 UINT64 OrMask;
1624 EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader;
1625 EFI_BOOT_SCRIPT_TABLE_HEADER TableHeader;
1626 Script = mS3BootScriptTablePtr->TableBase;
1627 if (Script != 0) {
1628 CopyMem ((VOID*)&TableHeader, Script, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));
1629 } else {
1630 return EFI_INVALID_PARAMETER;
1631 }
1632
1633 DEBUG ((EFI_D_INFO, "S3BootScriptExecute:\n"));
1634 if (TableHeader.OpCode != S3_BOOT_SCRIPT_LIB_TABLE_OPCODE) {
1635 return EFI_UNSUPPORTED;
1636 }
1637
1638 DEBUG ((EFI_D_INFO, "TableHeader - 0x%08x\n", Script));
1639
1640 StartAddress = (UINTN) Script;
1641 TableLength = TableHeader.TableLength;
1642 Script = Script + TableHeader.Length;
1643 Status = EFI_SUCCESS;
1644 AndMask = 0;
1645 OrMask = 0;
1646
1647 DEBUG ((EFI_D_INFO, "TableHeader.TableLength - 0x%08x\n", (UINTN)TableLength));
1648
1649 while ((UINTN) Script < (UINTN) (StartAddress + TableLength)) {
1650 DEBUG ((EFI_D_INFO, "ExecuteBootScript - %08x\n", (UINTN)Script));
1651
1652 CopyMem ((VOID*)&ScriptHeader, Script, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER));
1653 switch (ScriptHeader.OpCode) {
1654
1655 case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
1656 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE\n"));
1657 Status = BootScriptExecuteMemoryWrite (Script);
1658 break;
1659
1660 case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
1661 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE\n"));
1662 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1663 Status = BootScriptExecuteMemoryReadWrite (
1664 Script,
1665 AndMask,
1666 OrMask
1667 );
1668 break;
1669
1670 case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
1671 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_WRITE_OPCODE\n"));
1672 Status = BootScriptExecuteIoWrite (Script);
1673 break;
1674
1675 case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
1676 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE\n"));
1677 Status = BootScriptExecutePciCfgWrite (Script);
1678 break;
1679
1680 case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
1681 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE\n"));
1682 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1683 Status = BootScriptExecutePciCfgReadWrite (
1684 Script,
1685 AndMask,
1686 OrMask
1687 );
1688 break;
1689 case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE:
1690 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE\n"));
1691 Status = BootScriptExecutePciCfg2Write (Script);
1692 break;
1693
1694 case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
1695 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE\n"));
1696 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1697 Status = BootScriptExecutePciCfg2ReadWrite (
1698 Script,
1699 AndMask,
1700 OrMask
1701 );
1702 break;
1703 case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:
1704 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_DISPATCH_OPCODE\n"));
1705 Status = BootScriptExecuteDispatch (Script);
1706 break;
1707
1708 case EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE:
1709 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE\n"));
1710 Status = BootScriptExecuteDispatch2 (Script);
1711 break;
1712
1713 case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
1714 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_INFORMATION_OPCODE\n"));
1715 BootScriptExecuteInformation (Script);
1716 break;
1717
1718 case S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE:
1719 DEBUG ((EFI_D_INFO, "S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE\n"));
1720 DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", EFI_SUCCESS));
1721 return EFI_SUCCESS;
1722
1723 case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
1724 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE\n"));
1725 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1726 Status = BootScriptExecuteIoReadWrite (
1727 Script,
1728 AndMask,
1729 OrMask
1730 );
1731 break;
1732
1733 case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE:
1734 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE\n"));
1735 Status = BootScriptExecuteSmbusExecute (Script);
1736 break;
1737
1738 case EFI_BOOT_SCRIPT_STALL_OPCODE:
1739 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_STALL_OPCODE\n"));
1740 Status = BootScriptExecuteStall (Script);
1741 break;
1742
1743 case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
1744 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_POLL_OPCODE\n"));
1745 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1746 Status = BootScriptExecuteMemPoll (Script, AndMask, OrMask);
1747
1748 break;
1749
1750 case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
1751 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_POLL_OPCODE\n"));
1752 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1753 Status = BootScriptExecuteIoPoll (Script, AndMask, OrMask);
1754 break;
1755
1756 case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
1757 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE\n"));
1758 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1759 Status = BootScriptPciCfgPoll (Script, AndMask, OrMask);
1760 break;
1761
1762 case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
1763 DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE\n"));
1764 CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1765 Status = BootScriptPciCfg2Poll (Script, AndMask, OrMask);
1766 break;
1767
1768 case S3_BOOT_SCRIPT_LIB_LABEL_OPCODE:
1769 //
1770 // For label
1771 //
1772 DEBUG ((EFI_D_INFO, "S3_BOOT_SCRIPT_LIB_LABEL_OPCODE\n"));
1773 BootScriptExecuteLabel (Script);
1774 break;
1775 default:
1776 DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", EFI_UNSUPPORTED));
1777 return EFI_UNSUPPORTED;
1778 }
1779
1780 if (EFI_ERROR (Status)) {
1781 DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", Status));
1782 return Status;
1783 }
1784
1785 Script = Script + ScriptHeader.Length;
1786 }
1787
1788 DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", Status));
1789
1790 return Status;
1791 }
1792