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