1 /** @file
2   The multiple segments PCI configuration Library Services that carry out
3   PCI configuration and enable the PCI operations to be replayed during an
4   S3 resume. This library class maps directly on top of the PciSegmentLib class.
5 
6   Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
7   SPDX-License-Identifier: BSD-2-Clause-Patent
8 
9 **/
10 
11 
12 #include <Base.h>
13 
14 #include <Library/DebugLib.h>
15 #include <Library/S3BootScriptLib.h>
16 #include <Library/PciSegmentLib.h>
17 
18 /**
19   Macro that converts address in PciSegmentLib format to the new address that can be pass
20   to the S3 Boot Script Library functions. The Segment is dropped.
21 
22   @param Address  Address in PciSegmentLib format.
23 
24   @retval New address that can be pass to the S3 Boot Script Library functions.
25 **/
26 #define PCI_SEGMENT_LIB_ADDRESS_TO_S3_BOOT_SCRIPT_PCI_ADDRESS(Address) \
27           ((((UINT32)(Address) >> 20) & 0xff) << 24) | \
28           ((((UINT32)(Address) >> 15) & 0x1f) << 16) | \
29           ((((UINT32)(Address) >> 12) & 0x07) <<  8) | \
30           LShiftU64 ((Address) & 0xfff, 32)    // Always put Register in high four bytes.
31 
32 /**
33   Saves a PCI configuration value to the boot script.
34 
35   This internal worker function saves a PCI configuration value in
36   the S3 script to be replayed on S3 resume.
37 
38   If the saving process fails, then ASSERT().
39 
40   @param  Width   The width of PCI configuration.
41   @param  Address Address that encodes the PCI Bus, Device, Function and
42                   Register.
43   @param  Buffer  The buffer containing value.
44 
45 **/
46 VOID
InternalSavePciSegmentWriteValueToBootScript(IN S3_BOOT_SCRIPT_LIB_WIDTH Width,IN UINT64 Address,IN VOID * Buffer)47 InternalSavePciSegmentWriteValueToBootScript (
48   IN S3_BOOT_SCRIPT_LIB_WIDTH  Width,
49   IN UINT64                 Address,
50   IN VOID                   *Buffer
51   )
52 {
53   RETURN_STATUS                Status;
54 
55   Status = S3BootScriptSavePciCfg2Write (
56              Width,
57              RShiftU64 ((Address), 32) & 0xffff,
58              PCI_SEGMENT_LIB_ADDRESS_TO_S3_BOOT_SCRIPT_PCI_ADDRESS (Address),
59              1,
60              Buffer
61              );
62   ASSERT_RETURN_ERROR (Status);
63 }
64 
65 /**
66   Saves an 8-bit PCI configuration value to the boot script.
67 
68   This internal worker function saves an 8-bit PCI configuration value in
69   the S3 script to be replayed on S3 resume.
70 
71   If the saving process fails, then ASSERT().
72 
73   @param  Address Address that encodes the PCI Bus, Device, Function and
74                   Register.
75   @param  Value   The value saved to boot script.
76 
77   @return Value.
78 
79 **/
80 UINT8
InternalSavePciSegmentWrite8ValueToBootScript(IN UINT64 Address,IN UINT8 Value)81 InternalSavePciSegmentWrite8ValueToBootScript (
82   IN UINT64             Address,
83   IN UINT8              Value
84   )
85 {
86   InternalSavePciSegmentWriteValueToBootScript (S3BootScriptWidthUint8, Address, &Value);
87 
88   return Value;
89 }
90 
91 /**
92   Reads an 8-bit PCI configuration register, and saves the value in the S3 script to
93   be replayed on S3 resume.
94 
95   Reads and returns the 8-bit PCI configuration register specified by Address.
96   This function must guarantee that all PCI read and write operations are serialized.
97 
98   If any reserved bits in Address are set, then ASSERT().
99 
100   @param  Address   Address that encodes the PCI Segment, Bus, Device, Function, and Register.
101 
102   @return The 8-bit PCI configuration register specified by Address.
103 
104 **/
105 UINT8
106 EFIAPI
S3PciSegmentRead8(IN UINT64 Address)107 S3PciSegmentRead8 (
108   IN UINT64                    Address
109   )
110 {
111   return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentRead8 (Address));
112 }
113 
114 /**
115   Writes an 8-bit PCI configuration register, and saves the value in the S3 script to
116   be replayed on S3 resume.
117 
118   Writes the 8-bit PCI configuration register specified by Address with the value specified by Value.
119   Value is returned.  This function must guarantee that all PCI read and write operations are serialized.
120 
121   If any reserved bits in Address are set, then ASSERT().
122 
123   @param  Address     Address that encodes the PCI Segment, Bus, Device, Function, and Register.
124   @param  Value       The value to write.
125 
126   @return The value written to the PCI configuration register.
127 
128 **/
129 UINT8
130 EFIAPI
S3PciSegmentWrite8(IN UINT64 Address,IN UINT8 Value)131 S3PciSegmentWrite8 (
132   IN UINT64                    Address,
133   IN UINT8                     Value
134   )
135 {
136   return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentWrite8 (Address, Value));
137 }
138 
139 /**
140   Performs a bitwise OR of an 8-bit PCI configuration register with an 8-bit value, and saves
141   the value in the S3 script to be replayed on S3 resume.
142 
143   Reads the 8-bit PCI configuration register specified by Address,
144   performs a bitwise OR between the read result and the value specified by OrData,
145   and writes the result to the 8-bit PCI configuration register specified by Address.
146   The value written to the PCI configuration register is returned.
147   This function must guarantee that all PCI read and write operations are serialized.
148 
149   If any reserved bits in Address are set, then ASSERT().
150 
151   @param  Address   Address that encodes the PCI Segment, Bus, Device, Function, and Register.
152   @param  OrData    The value to OR with the PCI configuration register.
153 
154   @return The value written to the PCI configuration register.
155 
156 **/
157 UINT8
158 EFIAPI
S3PciSegmentOr8(IN UINT64 Address,IN UINT8 OrData)159 S3PciSegmentOr8 (
160   IN UINT64                    Address,
161   IN UINT8                     OrData
162   )
163 {
164   return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentOr8 (Address, OrData));
165 }
166 
167 /**
168   Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value, and
169   saves the value in the S3 script to be replayed on S3 resume.
170 
171   Reads the 8-bit PCI configuration register specified by Address,
172   performs a bitwise AND between the read result and the value specified by AndData,
173   and writes the result to the 8-bit PCI configuration register specified by Address.
174   The value written to the PCI configuration register is returned.
175   This function must guarantee that all PCI read and write operations are serialized.
176   If any reserved bits in Address are set, then ASSERT().
177 
178   @param  Address   Address that encodes the PCI Segment, Bus, Device, Function, and Register.
179   @param  AndData   The value to AND with the PCI configuration register.
180 
181   @return The value written to the PCI configuration register.
182 
183 **/
184 UINT8
185 EFIAPI
S3PciSegmentAnd8(IN UINT64 Address,IN UINT8 AndData)186 S3PciSegmentAnd8 (
187   IN UINT64                    Address,
188   IN UINT8                     AndData
189   )
190 {
191   return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentAnd8 (Address, AndData));
192 }
193 
194 /**
195   Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value,
196   followed a bitwise OR with another 8-bit value, and saves the value in the S3 script to
197   be replayed on S3 resume.
198 
199   Reads the 8-bit PCI configuration register specified by Address,
200   performs a bitwise AND between the read result and the value specified by AndData,
201   performs a bitwise OR between the result of the AND operation and the value specified by OrData,
202   and writes the result to the 8-bit PCI configuration register specified by Address.
203   The value written to the PCI configuration register is returned.
204   This function must guarantee that all PCI read and write operations are serialized.
205 
206   If any reserved bits in Address are set, then ASSERT().
207 
208   @param  Address   Address that encodes the PCI Segment, Bus, Device, Function, and Register.
209   @param  AndData    The value to AND with the PCI configuration register.
210   @param  OrData    The value to OR with the PCI configuration register.
211 
212   @return The value written to the PCI configuration register.
213 
214 **/
215 UINT8
216 EFIAPI
S3PciSegmentAndThenOr8(IN UINT64 Address,IN UINT8 AndData,IN UINT8 OrData)217 S3PciSegmentAndThenOr8 (
218   IN UINT64                    Address,
219   IN UINT8                     AndData,
220   IN UINT8                     OrData
221   )
222 {
223   return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentAndThenOr8 (Address, AndData, OrData));
224 }
225 
226 /**
227   Reads a bit field of a PCI configuration register, and saves the value in the
228   S3 script to be replayed on S3 resume.
229 
230   Reads the bit field in an 8-bit PCI configuration register. The bit field is
231   specified by the StartBit and the EndBit. The value of the bit field is
232   returned.
233 
234   If any reserved bits in Address are set, then ASSERT().
235   If StartBit is greater than 7, then ASSERT().
236   If EndBit is greater than 7, then ASSERT().
237   If EndBit is less than StartBit, then ASSERT().
238 
239   @param  Address   PCI configuration register to read.
240   @param  StartBit  The ordinal of the least significant bit in the bit field.
241                     Range 0..7.
242   @param  EndBit    The ordinal of the most significant bit in the bit field.
243                     Range 0..7.
244 
245   @return The value of the bit field read from the PCI configuration register.
246 
247 **/
248 UINT8
249 EFIAPI
S3PciSegmentBitFieldRead8(IN UINT64 Address,IN UINTN StartBit,IN UINTN EndBit)250 S3PciSegmentBitFieldRead8 (
251   IN UINT64                    Address,
252   IN UINTN                     StartBit,
253   IN UINTN                     EndBit
254   )
255 {
256   return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentBitFieldRead8 (Address, StartBit, EndBit));
257 }
258 
259 /**
260   Writes a bit field to a PCI configuration register, and saves the value in
261   the S3 script to be replayed on S3 resume.
262 
263   Writes Value to the bit field of the PCI configuration register. The bit
264   field is specified by the StartBit and the EndBit. All other bits in the
265   destination PCI configuration register are preserved. The new value of the
266   8-bit register is returned.
267 
268   If any reserved bits in Address are set, then ASSERT().
269   If StartBit is greater than 7, then ASSERT().
270   If EndBit is greater than 7, then ASSERT().
271   If EndBit is less than StartBit, then ASSERT().
272   If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
273 
274   @param  Address   PCI configuration register to write.
275   @param  StartBit  The ordinal of the least significant bit in the bit field.
276                     Range 0..7.
277   @param  EndBit    The ordinal of the most significant bit in the bit field.
278                     Range 0..7.
279   @param  Value     New value of the bit field.
280 
281   @return The value written back to the PCI configuration register.
282 
283 **/
284 UINT8
285 EFIAPI
S3PciSegmentBitFieldWrite8(IN UINT64 Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT8 Value)286 S3PciSegmentBitFieldWrite8 (
287   IN UINT64                    Address,
288   IN UINTN                     StartBit,
289   IN UINTN                     EndBit,
290   IN UINT8                     Value
291   )
292 {
293   return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentBitFieldWrite8 (Address, StartBit, EndBit, Value));
294 }
295 
296 /**
297   Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, writes
298   the result back to the bit field in the 8-bit port, and saves the value in the
299   S3 script to be replayed on S3 resume.
300 
301   Reads the 8-bit PCI configuration register specified by Address, performs a
302   bitwise OR between the read result and the value specified by
303   OrData, and writes the result to the 8-bit PCI configuration register
304   specified by Address. The value written to the PCI configuration register is
305   returned. This function must guarantee that all PCI read and write operations
306   are serialized. Extra left bits in OrData are stripped.
307 
308   If any reserved bits in Address are set, then ASSERT().
309   If StartBit is greater than 7, then ASSERT().
310   If EndBit is greater than 7, then ASSERT().
311   If EndBit is less than StartBit, then ASSERT().
312   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
313 
314   @param  Address   PCI configuration register to write.
315   @param  StartBit  The ordinal of the least significant bit in the bit field.
316                     Range 0..7.
317   @param  EndBit    The ordinal of the most significant bit in the bit field.
318                     Range 0..7.
319   @param  OrData    The value to OR with the PCI configuration register.
320 
321   @return The value written back to the PCI configuration register.
322 
323 **/
324 UINT8
325 EFIAPI
S3PciSegmentBitFieldOr8(IN UINT64 Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT8 OrData)326 S3PciSegmentBitFieldOr8 (
327   IN UINT64                    Address,
328   IN UINTN                     StartBit,
329   IN UINTN                     EndBit,
330   IN UINT8                     OrData
331   )
332 {
333   return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentBitFieldOr8 (Address, StartBit, EndBit, OrData));
334 }
335 
336 /**
337   Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
338   AND, writes the result back to the bit field in the 8-bit register, and
339   saves the value in the S3 script to be replayed on S3 resume.
340 
341   Reads the 8-bit PCI configuration register specified by Address, performs a
342   bitwise AND between the read result and the value specified by AndData, and
343   writes the result to the 8-bit PCI configuration register specified by
344   Address. The value written to the PCI configuration register is returned.
345   This function must guarantee that all PCI read and write operations are
346   serialized. Extra left bits in AndData are stripped.
347 
348   If any reserved bits in Address are set, then ASSERT().
349   If StartBit is greater than 7, then ASSERT().
350   If EndBit is greater than 7, then ASSERT().
351   If EndBit is less than StartBit, then ASSERT().
352   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
353 
354   @param  Address   PCI configuration register to write.
355   @param  StartBit  The ordinal of the least significant bit in the bit field.
356                     Range 0..7.
357   @param  EndBit    The ordinal of the most significant bit in the bit field.
358                     Range 0..7.
359   @param  AndData   The value to AND with the PCI configuration register.
360 
361   @return The value written back to the PCI configuration register.
362 
363 **/
364 UINT8
365 EFIAPI
S3PciSegmentBitFieldAnd8(IN UINT64 Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT8 AndData)366 S3PciSegmentBitFieldAnd8 (
367   IN UINT64                    Address,
368   IN UINTN                     StartBit,
369   IN UINTN                     EndBit,
370   IN UINT8                     AndData
371   )
372 {
373   return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentBitFieldAnd8 (Address, StartBit, EndBit, AndData));
374 }
375 
376 /**
377   Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
378   bitwise OR, writes the result back to the bit field in the 8-bit port,
379   and saves the value in the S3 script to be replayed on S3 resume.
380 
381   Reads the 8-bit PCI configuration register specified by Address, performs a
382   bitwise AND followed by a bitwise OR between the read result and
383   the value specified by AndData, and writes the result to the 8-bit PCI
384   configuration register specified by Address. The value written to the PCI
385   configuration register is returned. This function must guarantee that all PCI
386   read and write operations are serialized. Extra left bits in both AndData and
387   OrData are stripped.
388 
389   If any reserved bits in Address are set, then ASSERT().
390   If StartBit is greater than 7, then ASSERT().
391   If EndBit is greater than 7, then ASSERT().
392   If EndBit is less than StartBit, then ASSERT().
393   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
394   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
395 
396   @param  Address   PCI configuration register to write.
397   @param  StartBit  The ordinal of the least significant bit in the bit field.
398                     Range 0..7.
399   @param  EndBit    The ordinal of the most significant bit in the bit field.
400                     Range 0..7.
401   @param  AndData   The value to AND with the PCI configuration register.
402   @param  OrData    The value to OR with the result of the AND operation.
403 
404   @return The value written back to the PCI configuration register.
405 
406 **/
407 UINT8
408 EFIAPI
S3PciSegmentBitFieldAndThenOr8(IN UINT64 Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT8 AndData,IN UINT8 OrData)409 S3PciSegmentBitFieldAndThenOr8 (
410   IN UINT64                    Address,
411   IN UINTN                     StartBit,
412   IN UINTN                     EndBit,
413   IN UINT8                     AndData,
414   IN UINT8                     OrData
415   )
416 {
417   return InternalSavePciSegmentWrite8ValueToBootScript (Address, PciSegmentBitFieldAndThenOr8 (Address, StartBit, EndBit, AndData, OrData));
418 }
419 
420 /**
421   Saves a 16-bit PCI configuration value to the boot script.
422 
423   This internal worker function saves a 16-bit PCI configuration value in
424   the S3 script to be replayed on S3 resume.
425 
426   If the saving process fails, then ASSERT().
427 
428   @param  Address Address that encodes the PCI Bus, Device, Function and
429                   Register.
430   @param  Value   The value saved to boot script.
431 
432   @return Value.
433 
434 **/
435 UINT16
InternalSavePciSegmentWrite16ValueToBootScript(IN UINT64 Address,IN UINT16 Value)436 InternalSavePciSegmentWrite16ValueToBootScript (
437   IN UINT64             Address,
438   IN UINT16             Value
439   )
440 {
441   InternalSavePciSegmentWriteValueToBootScript (S3BootScriptWidthUint16, Address, &Value);
442 
443   return Value;
444 }
445 
446 /**
447   Reads a 16-bit PCI configuration register, and saves the value in the S3 script
448   to be replayed on S3 resume.
449 
450   Reads and returns the 16-bit PCI configuration register specified by Address.
451   This function must guarantee that all PCI read and write operations are serialized.
452 
453   If any reserved bits in Address are set, then ASSERT().
454   If Address is not aligned on a 16-bit boundary, then ASSERT().
455 
456   @param  Address   Address that encodes the PCI Segment, Bus, Device, Function, and Register.
457 
458   @return The 16-bit PCI configuration register specified by Address.
459 
460 **/
461 UINT16
462 EFIAPI
S3PciSegmentRead16(IN UINT64 Address)463 S3PciSegmentRead16 (
464   IN UINT64                    Address
465   )
466 {
467   return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentRead16 (Address));
468 }
469 
470 /**
471   Writes a 16-bit PCI configuration register, and saves the value in the S3 script to
472   be replayed on S3 resume.
473 
474   Writes the 16-bit PCI configuration register specified by Address with the value specified by Value.
475   Value is returned.  This function must guarantee that all PCI read and write operations are serialized.
476 
477   If any reserved bits in Address are set, then ASSERT().
478   If Address is not aligned on a 16-bit boundary, then ASSERT().
479 
480   @param  Address     Address that encodes the PCI Segment, Bus, Device, Function, and Register.
481   @param  Value       The value to write.
482 
483   @return The parameter of Value.
484 
485 **/
486 UINT16
487 EFIAPI
S3PciSegmentWrite16(IN UINT64 Address,IN UINT16 Value)488 S3PciSegmentWrite16 (
489   IN UINT64                    Address,
490   IN UINT16                    Value
491   )
492 {
493   return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentWrite16 (Address, Value));
494 }
495 
496 /**
497   Performs a bitwise OR of a 16-bit PCI configuration register with a 16-bit
498   value, and saves the value in the S3 script to be replayed on S3 resume.
499 
500   Reads the 16-bit PCI configuration register specified by Address, performs a
501   bitwise OR between the read result and the value specified by OrData, and
502   writes the result to the 16-bit PCI configuration register specified by Address.
503   The value written to the PCI configuration register is returned. This function
504   must guarantee that all PCI read and write operations are serialized.
505 
506   If any reserved bits in Address are set, then ASSERT().
507   If Address is not aligned on a 16-bit boundary, then ASSERT().
508 
509   @param  Address Address that encodes the PCI Segment, Bus, Device, Function and
510                   Register.
511   @param  OrData  The value to OR with the PCI configuration register.
512 
513   @return The value written back to the PCI configuration register.
514 
515 **/
516 UINT16
517 EFIAPI
S3PciSegmentOr16(IN UINT64 Address,IN UINT16 OrData)518 S3PciSegmentOr16 (
519   IN UINT64                    Address,
520   IN UINT16                    OrData
521   )
522 {
523   return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentOr16 (Address, OrData));
524 }
525 
526 /**
527   Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value, and
528   saves the value in the S3 script to be replayed on S3 resume.
529 
530   Reads the 16-bit PCI configuration register specified by Address,
531   performs a bitwise AND between the read result and the value specified by AndData,
532   and writes the result to the 16-bit PCI configuration register specified by Address.
533   The value written to the PCI configuration register is returned.
534   This function must guarantee that all PCI read and write operations are serialized.
535 
536   If any reserved bits in Address are set, then ASSERT().
537   If Address is not aligned on a 16-bit boundary, then ASSERT().
538 
539   @param  Address   Address that encodes the PCI Segment, Bus, Device, Function, and Register.
540   @param  AndData   The value to AND with the PCI configuration register.
541 
542   @return The value written to the PCI configuration register.
543 
544 **/
545 UINT16
546 EFIAPI
S3PciSegmentAnd16(IN UINT64 Address,IN UINT16 AndData)547 S3PciSegmentAnd16 (
548   IN UINT64                    Address,
549   IN UINT16                    AndData
550   )
551 {
552   return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentAnd16 (Address, AndData));
553 }
554 
555 /**
556   Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value,
557   followed a bitwise OR with another 16-bit value, and saves the value in the S3 script to
558   be replayed on S3 resume.
559 
560   Reads the 16-bit PCI configuration register specified by Address,
561   performs a bitwise AND between the read result and the value specified by AndData,
562   performs a bitwise OR between the result of the AND operation and the value specified by OrData,
563   and writes the result to the 16-bit PCI configuration register specified by Address.
564   The value written to the PCI configuration register is returned.
565   This function must guarantee that all PCI read and write operations are serialized.
566 
567   If any reserved bits in Address are set, then ASSERT().
568   If Address is not aligned on a 16-bit boundary, then ASSERT().
569 
570   @param  Address   Address that encodes the PCI Segment, Bus, Device, Function, and Register.
571   @param  AndData   The value to AND with the PCI configuration register.
572   @param  OrData    The value to OR with the PCI configuration register.
573 
574   @return The value written to the PCI configuration register.
575 
576 **/
577 UINT16
578 EFIAPI
S3PciSegmentAndThenOr16(IN UINT64 Address,IN UINT16 AndData,IN UINT16 OrData)579 S3PciSegmentAndThenOr16 (
580   IN UINT64                    Address,
581   IN UINT16                    AndData,
582   IN UINT16                    OrData
583   )
584 {
585   return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentAndThenOr16 (Address, AndData, OrData));
586 }
587 
588 /**
589   Reads a bit field of a PCI configuration register, and saves the value in the
590   S3 script to be replayed on S3 resume.
591 
592   Reads the bit field in a 16-bit PCI configuration register. The bit field is
593   specified by the StartBit and the EndBit. The value of the bit field is
594   returned.
595 
596   If any reserved bits in Address are set, then ASSERT().
597   If Address is not aligned on a 16-bit boundary, then ASSERT().
598   If StartBit is greater than 15, then ASSERT().
599   If EndBit is greater than 15, then ASSERT().
600   If EndBit is less than StartBit, then ASSERT().
601 
602   @param  Address   PCI configuration register to read.
603   @param  StartBit  The ordinal of the least significant bit in the bit field.
604                     Range 0..15.
605   @param  EndBit    The ordinal of the most significant bit in the bit field.
606                     Range 0..15.
607 
608   @return The value of the bit field read from the PCI configuration register.
609 
610 **/
611 UINT16
612 EFIAPI
S3PciSegmentBitFieldRead16(IN UINT64 Address,IN UINTN StartBit,IN UINTN EndBit)613 S3PciSegmentBitFieldRead16 (
614   IN UINT64                    Address,
615   IN UINTN                     StartBit,
616   IN UINTN                     EndBit
617   )
618 {
619   return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentBitFieldRead16 (Address, StartBit, EndBit));
620 }
621 
622 /**
623   Writes a bit field to a PCI configuration register, and saves the value in
624   the S3 script to be replayed on S3 resume.
625 
626   Writes Value to the bit field of the PCI configuration register. The bit
627   field is specified by the StartBit and the EndBit. All other bits in the
628   destination PCI configuration register are preserved. The new value of the
629   16-bit register is returned.
630 
631   If any reserved bits in Address are set, then ASSERT().
632   If Address is not aligned on a 16-bit boundary, then ASSERT().
633   If StartBit is greater than 15, then ASSERT().
634   If EndBit is greater than 15, then ASSERT().
635   If EndBit is less than StartBit, then ASSERT().
636   If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
637 
638   @param  Address   PCI configuration register to write.
639   @param  StartBit  The ordinal of the least significant bit in the bit field.
640                     Range 0..15.
641   @param  EndBit    The ordinal of the most significant bit in the bit field.
642                     Range 0..15.
643   @param  Value     New value of the bit field.
644 
645   @return The value written back to the PCI configuration register.
646 
647 **/
648 UINT16
649 EFIAPI
S3PciSegmentBitFieldWrite16(IN UINT64 Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT16 Value)650 S3PciSegmentBitFieldWrite16 (
651   IN UINT64                    Address,
652   IN UINTN                     StartBit,
653   IN UINTN                     EndBit,
654   IN UINT16                    Value
655   )
656 {
657   return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentBitFieldWrite16 (Address, StartBit, EndBit, Value));
658 }
659 
660 /**
661   Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, writes
662   the result back to the bit field in the 16-bit port, and saves the value in the
663   S3 script to be replayed on S3 resume.
664 
665   Reads the 16-bit PCI configuration register specified by Address, performs a
666   bitwise OR between the read result and the value specified by
667   OrData, and writes the result to the 16-bit PCI configuration register
668   specified by Address. The value written to the PCI configuration register is
669   returned. This function must guarantee that all PCI read and write operations
670   are serialized. Extra left bits in OrData are stripped.
671 
672   If any reserved bits in Address are set, then ASSERT().
673   If Address is not aligned on a 16-bit boundary, then ASSERT().
674   If StartBit is greater than 15, then ASSERT().
675   If EndBit is greater than 15, then ASSERT().
676   If EndBit is less than StartBit, then ASSERT().
677   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
678 
679   @param  Address   PCI configuration register to write.
680   @param  StartBit  The ordinal of the least significant bit in the bit field.
681                     Range 0..15.
682   @param  EndBit    The ordinal of the most significant bit in the bit field.
683                     Range 0..15.
684   @param  OrData    The value to OR with the PCI configuration register.
685 
686   @return The value written back to the PCI configuration register.
687 
688 **/
689 UINT16
690 EFIAPI
S3PciSegmentBitFieldOr16(IN UINT64 Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT16 OrData)691 S3PciSegmentBitFieldOr16 (
692   IN UINT64                    Address,
693   IN UINTN                     StartBit,
694   IN UINTN                     EndBit,
695   IN UINT16                    OrData
696   )
697 {
698   return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentBitFieldOr16 (Address, StartBit, EndBit, OrData));
699 }
700 
701 /**
702   Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
703   AND, writes the result back to the bit field in the 16-bit register, and
704   saves the value in the S3 script to be replayed on S3 resume.
705 
706   Reads the 16-bit PCI configuration register specified by Address, performs a
707   bitwise AND between the read result and the value specified by AndData, and
708   writes the result to the 16-bit PCI configuration register specified by
709   Address. The value written to the PCI configuration register is returned.
710   This function must guarantee that all PCI read and write operations are
711   serialized. Extra left bits in AndData are stripped.
712 
713   If any reserved bits in Address are set, then ASSERT().
714   If Address is not aligned on a 16-bit boundary, then ASSERT().
715   If StartBit is greater than 15, then ASSERT().
716   If EndBit is greater than 15, then ASSERT().
717   If EndBit is less than StartBit, then ASSERT().
718   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
719 
720   @param  Address   Address that encodes the PCI Segment, Bus, Device, Function, and Register.
721   @param  StartBit  The ordinal of the least significant bit in the bit field.
722                     Range 0..15.
723   @param  EndBit    The ordinal of the most significant bit in the bit field.
724                     Range 0..15.
725   @param  AndData   The value to AND with the PCI configuration register.
726 
727   @return The value written back to the PCI configuration register.
728 
729 **/
730 UINT16
731 EFIAPI
S3PciSegmentBitFieldAnd16(IN UINT64 Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT16 AndData)732 S3PciSegmentBitFieldAnd16 (
733   IN UINT64                    Address,
734   IN UINTN                     StartBit,
735   IN UINTN                     EndBit,
736   IN UINT16                    AndData
737   )
738 {
739   return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentBitFieldAnd16 (Address, StartBit, EndBit, AndData));
740 }
741 
742 /**
743   Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
744   bitwise OR, writes the result back to the bit field in the 16-bit port,
745   and saves the value in the S3 script to be replayed on S3 resume.
746 
747   Reads the 16-bit PCI configuration register specified by Address, performs a
748   bitwise AND followed by a bitwise OR between the read result and
749   the value specified by AndData, and writes the result to the 16-bit PCI
750   configuration register specified by Address. The value written to the PCI
751   configuration register is returned. This function must guarantee that all PCI
752   read and write operations are serialized. Extra left bits in both AndData and
753   OrData are stripped.
754 
755   If any reserved bits in Address are set, then ASSERT().
756   If StartBit is greater than 15, then ASSERT().
757   If EndBit is greater than 15, then ASSERT().
758   If EndBit is less than StartBit, then ASSERT().
759   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
760   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
761 
762   @param  Address   PCI configuration register to write.
763   @param  StartBit  The ordinal of the least significant bit in the bit field.
764                     Range 0..15.
765   @param  EndBit    The ordinal of the most significant bit in the bit field.
766                     Range 0..15.
767   @param  AndData   The value to AND with the PCI configuration register.
768   @param  OrData    The value to OR with the result of the AND operation.
769 
770   @return The value written back to the PCI configuration register.
771 
772 **/
773 UINT16
774 EFIAPI
S3PciSegmentBitFieldAndThenOr16(IN UINT64 Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT16 AndData,IN UINT16 OrData)775 S3PciSegmentBitFieldAndThenOr16 (
776   IN UINT64                    Address,
777   IN UINTN                     StartBit,
778   IN UINTN                     EndBit,
779   IN UINT16                    AndData,
780   IN UINT16                    OrData
781   )
782 {
783   return InternalSavePciSegmentWrite16ValueToBootScript (Address, PciSegmentBitFieldAndThenOr16 (Address, StartBit, EndBit, AndData, OrData));
784 }
785 
786 
787 
788 /**
789   Saves a 32-bit PCI configuration value to the boot script.
790 
791   This internal worker function saves a 32-bit PCI configuration value in the S3 script
792   to be replayed on S3 resume.
793 
794   If the saving process fails, then ASSERT().
795 
796   @param  Address Address that encodes the PCI Bus, Device, Function and
797                   Register.
798   @param  Value   The value saved to boot script.
799 
800   @return Value.
801 
802 **/
803 UINT32
InternalSavePciSegmentWrite32ValueToBootScript(IN UINT64 Address,IN UINT32 Value)804 InternalSavePciSegmentWrite32ValueToBootScript (
805   IN UINT64             Address,
806   IN UINT32             Value
807   )
808 {
809   InternalSavePciSegmentWriteValueToBootScript (S3BootScriptWidthUint32, Address, &Value);
810 
811   return Value;
812 }
813 
814 /**
815   Reads a 32-bit PCI configuration register, and saves the value in the S3 script
816   to be replayed on S3 resume.
817 
818   Reads and returns the 32-bit PCI configuration register specified by Address.
819   This function must guarantee that all PCI read and write operations are serialized.
820 
821   If any reserved bits in Address are set, then ASSERT().
822   If Address is not aligned on a 32-bit boundary, then ASSERT().
823 
824   @param  Address   Address that encodes the PCI Segment, Bus, Device, Function, and Register.
825 
826   @return The 32-bit PCI configuration register specified by Address.
827 
828 **/
829 UINT32
830 EFIAPI
S3PciSegmentRead32(IN UINT64 Address)831 S3PciSegmentRead32 (
832   IN UINT64                    Address
833   )
834 {
835   return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentRead32 (Address));
836 }
837 
838 /**
839   Writes a 32-bit PCI configuration register, and saves the value in the S3 script to
840   be replayed on S3 resume.
841 
842   Writes the 32-bit PCI configuration register specified by Address with the value specified by Value.
843   Value is returned.  This function must guarantee that all PCI read and write operations are serialized.
844 
845   If any reserved bits in Address are set, then ASSERT().
846   If Address is not aligned on a 32-bit boundary, then ASSERT().
847 
848   @param  Address     Address that encodes the PCI Segment, Bus, Device, Function, and Register.
849   @param  Value       The value to write.
850 
851   @return The parameter of Value.
852 
853 **/
854 UINT32
855 EFIAPI
S3PciSegmentWrite32(IN UINT64 Address,IN UINT32 Value)856 S3PciSegmentWrite32 (
857   IN UINT64                    Address,
858   IN UINT32                    Value
859   )
860 {
861   return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentWrite32 (Address, Value));
862 }
863 
864 /**
865   Performs a bitwise OR of a 32-bit PCI configuration register with a 32-bit
866   value, and saves the value in the S3 script to be replayed on S3 resume.
867 
868   Reads the 32-bit PCI configuration register specified by Address, performs a
869   bitwise OR between the read result and the value specified by OrData, and
870   writes the result to the 32-bit PCI configuration register specified by Address.
871   The value written to the PCI configuration register is returned. This function
872   must guarantee that all PCI read and write operations are serialized.
873 
874   If any reserved bits in Address are set, then ASSERT().
875   If Address is not aligned on a 32-bit boundary, then ASSERT().
876 
877   @param  Address   Address that encodes the PCI Segment, Bus, Device, Function, and
878                     Register.
879   @param  OrData    The value to OR with the PCI configuration register.
880 
881   @return The value written back to the PCI configuration register.
882 
883 **/
884 UINT32
885 EFIAPI
S3PciSegmentOr32(IN UINT64 Address,IN UINT32 OrData)886 S3PciSegmentOr32 (
887   IN UINT64                    Address,
888   IN UINT32                    OrData
889   )
890 {
891   return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentOr32 (Address, OrData));
892 }
893 
894 /**
895   Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value, and
896   saves the value in the S3 script to be replayed on S3 resume.
897 
898   Reads the 32-bit PCI configuration register specified by Address,
899   performs a bitwise AND between the read result and the value specified by AndData,
900   and writes the result to the 32-bit PCI configuration register specified by Address.
901   The value written to the PCI configuration register is returned.
902   This function must guarantee that all PCI read and write operations are serialized.
903 
904   If any reserved bits in Address are set, then ASSERT().
905   If Address is not aligned on a 32-bit boundary, then ASSERT().
906 
907   @param  Address   Address that encodes the PCI Segment, Bus, Device, Function, and Register.
908   @param  AndData   The value to AND with the PCI configuration register.
909 
910   @return The value written to the PCI configuration register.
911 
912 **/
913 UINT32
914 EFIAPI
S3PciSegmentAnd32(IN UINT64 Address,IN UINT32 AndData)915 S3PciSegmentAnd32 (
916   IN UINT64                    Address,
917   IN UINT32                    AndData
918   )
919 {
920   return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentAnd32 (Address, AndData));
921 }
922 
923 /**
924   Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value,
925   followed a bitwise OR with another 32-bit value, and saves the value in the S3 script to
926   be replayed on S3 resume.
927 
928   Reads the 32-bit PCI configuration register specified by Address,
929   performs a bitwise AND between the read result and the value specified by AndData,
930   performs a bitwise OR between the result of the AND operation and the value specified by OrData,
931   and writes the result to the 32-bit PCI configuration register specified by Address.
932   The value written to the PCI configuration register is returned.
933   This function must guarantee that all PCI read and write operations are serialized.
934 
935   If any reserved bits in Address are set, then ASSERT().
936   If Address is not aligned on a 32-bit boundary, then ASSERT().
937 
938   @param  Address   Address that encodes the PCI Segment, Bus, Device, Function, and Register.
939   @param  AndData   The value to AND with the PCI configuration register.
940   @param  OrData    The value to OR with the PCI configuration register.
941 
942   @return The value written to the PCI configuration register.
943 
944 **/
945 UINT32
946 EFIAPI
S3PciSegmentAndThenOr32(IN UINT64 Address,IN UINT32 AndData,IN UINT32 OrData)947 S3PciSegmentAndThenOr32 (
948   IN UINT64                    Address,
949   IN UINT32                    AndData,
950   IN UINT32                    OrData
951   )
952 {
953   return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentAndThenOr32 (Address, AndData, OrData));
954 }
955 
956 /**
957   Reads a bit field of a PCI configuration register, and saves the value in the
958   S3 script to be replayed on S3 resume.
959 
960   Reads the bit field in a 32-bit PCI configuration register. The bit field is
961   specified by the StartBit and the EndBit. The value of the bit field is
962   returned.
963 
964   If any reserved bits in Address are set, then ASSERT().
965   If Address is not aligned on a 32-bit boundary, then ASSERT().
966   If StartBit is greater than 31, then ASSERT().
967   If EndBit is greater than 31, then ASSERT().
968   If EndBit is less than StartBit, then ASSERT().
969 
970   @param  Address   PCI configuration register to read.
971   @param  StartBit  The ordinal of the least significant bit in the bit field.
972                     Range 0..31.
973   @param  EndBit    The ordinal of the most significant bit in the bit field.
974                     Range 0..31.
975 
976   @return The value of the bit field read from the PCI configuration register.
977 
978 **/
979 UINT32
980 EFIAPI
S3PciSegmentBitFieldRead32(IN UINT64 Address,IN UINTN StartBit,IN UINTN EndBit)981 S3PciSegmentBitFieldRead32 (
982   IN UINT64                    Address,
983   IN UINTN                     StartBit,
984   IN UINTN                     EndBit
985   )
986 {
987   return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentBitFieldRead32 (Address, StartBit, EndBit));
988 }
989 
990 /**
991   Writes a bit field to a PCI configuration register, and saves the value in
992   the S3 script to be replayed on S3 resume.
993 
994   Writes Value to the bit field of the PCI configuration register. The bit
995   field is specified by the StartBit and the EndBit. All other bits in the
996   destination PCI configuration register are preserved. The new value of the
997   32-bit register is returned.
998 
999   If any reserved bits in Address are set, then ASSERT().
1000   If Address is not aligned on a 32-bit boundary, then ASSERT().
1001   If StartBit is greater than 31, then ASSERT().
1002   If EndBit is greater than 31, then ASSERT().
1003   If EndBit is less than StartBit, then ASSERT().
1004   If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1005 
1006   @param  Address   PCI configuration register to write.
1007   @param  StartBit  The ordinal of the least significant bit in the bit field.
1008                     Range 0..31.
1009   @param  EndBit    The ordinal of the most significant bit in the bit field.
1010                     Range 0..31.
1011   @param  Value     New value of the bit field.
1012 
1013   @return The value written back to the PCI configuration register.
1014 
1015 **/
1016 UINT32
1017 EFIAPI
S3PciSegmentBitFieldWrite32(IN UINT64 Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT32 Value)1018 S3PciSegmentBitFieldWrite32 (
1019   IN UINT64                    Address,
1020   IN UINTN                     StartBit,
1021   IN UINTN                     EndBit,
1022   IN UINT32                    Value
1023   )
1024 {
1025   return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentBitFieldWrite32 (Address, StartBit, EndBit, Value));
1026 }
1027 
1028 /**
1029   Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, writes
1030   the result back to the bit field in the 32-bit port, and saves the value in the
1031   S3 script to be replayed on S3 resume.
1032 
1033   Reads the 32-bit PCI configuration register specified by Address, performs a
1034   bitwise OR between the read result and the value specified by
1035   OrData, and writes the result to the 32-bit PCI configuration register
1036   specified by Address. The value written to the PCI configuration register is
1037   returned. This function must guarantee that all PCI read and write operations
1038   are serialized. Extra left bits in OrData are stripped.
1039 
1040   If any reserved bits in Address are set, then ASSERT().
1041   If Address is not aligned on a 32-bit boundary, then ASSERT().
1042   If StartBit is greater than 31, then ASSERT().
1043   If EndBit is greater than 31, then ASSERT().
1044   If EndBit is less than StartBit, then ASSERT().
1045   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1046 
1047   @param  Address   PCI configuration register to write.
1048   @param  StartBit  The ordinal of the least significant bit in the bit field.
1049                     Range 0..31.
1050   @param  EndBit    The ordinal of the most significant bit in the bit field.
1051                     Range 0..31.
1052   @param  OrData    The value to OR with the PCI configuration register.
1053 
1054   @return The value written back to the PCI configuration register.
1055 
1056 **/
1057 UINT32
1058 EFIAPI
S3PciSegmentBitFieldOr32(IN UINT64 Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT32 OrData)1059 S3PciSegmentBitFieldOr32 (
1060   IN UINT64                    Address,
1061   IN UINTN                     StartBit,
1062   IN UINTN                     EndBit,
1063   IN UINT32                    OrData
1064   )
1065 {
1066   return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentBitFieldOr32 (Address, StartBit, EndBit, OrData));
1067 }
1068 
1069 /**
1070   Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
1071   AND, and writes the result back to the bit field in the 32-bit register, and
1072   saves the value in the S3 script to be replayed on S3 resume.
1073 
1074   Reads the 32-bit PCI configuration register specified by Address, performs a
1075   bitwise AND between the read result and the value specified by AndData, and
1076   writes the result to the 32-bit PCI configuration register specified by
1077   Address. The value written to the PCI configuration register is returned.
1078   This function must guarantee that all PCI read and write operations are
1079   serialized. Extra left bits in AndData are stripped.
1080 
1081   If any reserved bits in Address are set, then ASSERT().
1082   If Address is not aligned on a 32-bit boundary, then ASSERT().
1083   If StartBit is greater than 31, then ASSERT().
1084   If EndBit is greater than 31, then ASSERT().
1085   If EndBit is less than StartBit, then ASSERT().
1086   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1087 
1088   @param  Address   Address that encodes the PCI Segment, Bus, Device, Function, and Register.
1089   @param  StartBit  The ordinal of the least significant bit in the bit field.
1090                     Range 0..31.
1091   @param  EndBit    The ordinal of the most significant bit in the bit field.
1092                     Range 0..31.
1093   @param  AndData   The value to AND with the PCI configuration register.
1094 
1095   @return The value written back to the PCI configuration register.
1096 
1097 **/
1098 UINT32
1099 EFIAPI
S3PciSegmentBitFieldAnd32(IN UINT64 Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT32 AndData)1100 S3PciSegmentBitFieldAnd32 (
1101   IN UINT64                    Address,
1102   IN UINTN                     StartBit,
1103   IN UINTN                     EndBit,
1104   IN UINT32                    AndData
1105   )
1106 {
1107   return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentBitFieldAnd32 (Address, StartBit, EndBit, AndData));
1108 }
1109 
1110 /**
1111   Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
1112   bitwise OR, writes the result back to the bit field in the 32-bit port,
1113   and saves the value in the S3 script to be replayed on S3 resume.
1114 
1115   Reads the 32-bit PCI configuration register specified by Address, performs a
1116   bitwise AND followed by a bitwise OR between the read result and
1117   the value specified by AndData, and writes the result to the 32-bit PCI
1118   configuration register specified by Address. The value written to the PCI
1119   configuration register is returned. This function must guarantee that all PCI
1120   read and write operations are serialized. Extra left bits in both AndData and
1121   OrData are stripped.
1122 
1123   If any reserved bits in Address are set, then ASSERT().
1124   If StartBit is greater than 31, then ASSERT().
1125   If EndBit is greater than 31, then ASSERT().
1126   If EndBit is less than StartBit, then ASSERT().
1127   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1128   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
1129 
1130   @param  Address   PCI configuration register to write.
1131   @param  StartBit  The ordinal of the least significant bit in the bit field.
1132                     Range 0..31.
1133   @param  EndBit    The ordinal of the most significant bit in the bit field.
1134                     Range 0..31.
1135   @param  AndData   The value to AND with the PCI configuration register.
1136   @param  OrData    The value to OR with the result of the AND operation.
1137 
1138   @return The value written back to the PCI configuration register.
1139 
1140 **/
1141 UINT32
1142 EFIAPI
S3PciSegmentBitFieldAndThenOr32(IN UINT64 Address,IN UINTN StartBit,IN UINTN EndBit,IN UINT32 AndData,IN UINT32 OrData)1143 S3PciSegmentBitFieldAndThenOr32 (
1144   IN UINT64                    Address,
1145   IN UINTN                     StartBit,
1146   IN UINTN                     EndBit,
1147   IN UINT32                    AndData,
1148   IN UINT32                    OrData
1149   )
1150 {
1151   return InternalSavePciSegmentWrite32ValueToBootScript (Address, PciSegmentBitFieldAndThenOr32 (Address, StartBit, EndBit, AndData, OrData));
1152 }
1153 
1154 /**
1155   Reads a range of PCI configuration registers into a caller supplied buffer,
1156   and saves the value in the S3 script to be replayed on S3 resume.
1157 
1158   Reads the range of PCI configuration registers specified by StartAddress and
1159   Size into the buffer specified by Buffer. This function only allows the PCI
1160   configuration registers from a single PCI function to be read. Size is
1161   returned. When possible 32-bit PCI configuration read cycles are used to read
1162   from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit
1163   and 16-bit PCI configuration read cycles may be used at the beginning and the
1164   end of the range.
1165 
1166   If any reserved bits in StartAddress are set, then ASSERT().
1167   If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
1168   If Size > 0 and Buffer is NULL, then ASSERT().
1169 
1170   @param  StartAddress  Starting address that encodes the PCI Segment, Bus, Device,
1171                         Function and Register.
1172   @param  Size          Size in bytes of the transfer.
1173   @param  Buffer        Pointer to a buffer receiving the data read.
1174 
1175   @return Size
1176 
1177 **/
1178 UINTN
1179 EFIAPI
S3PciSegmentReadBuffer(IN UINT64 StartAddress,IN UINTN Size,OUT VOID * Buffer)1180 S3PciSegmentReadBuffer (
1181   IN  UINT64                   StartAddress,
1182   IN  UINTN                    Size,
1183   OUT VOID                     *Buffer
1184   )
1185 {
1186   RETURN_STATUS    Status;
1187 
1188   Status = S3BootScriptSavePciCfg2Write (
1189              S3BootScriptWidthUint8,
1190              RShiftU64 (StartAddress, 32) & 0xffff,
1191              PCI_SEGMENT_LIB_ADDRESS_TO_S3_BOOT_SCRIPT_PCI_ADDRESS (StartAddress),
1192              PciSegmentReadBuffer (StartAddress, Size, Buffer),
1193              Buffer
1194              );
1195   ASSERT_RETURN_ERROR (Status);
1196   return Size;
1197 }
1198 
1199 /**
1200   Copies the data in a caller supplied buffer to a specified range of PCI
1201   configuration space, and saves the value in the S3 script to be replayed on S3
1202   resume.
1203 
1204   Writes the range of PCI configuration registers specified by StartAddress and
1205   Size from the buffer specified by Buffer. This function only allows the PCI
1206   configuration registers from a single PCI function to be written. Size is
1207   returned. When possible 32-bit PCI configuration write cycles are used to
1208   write from StartAdress to StartAddress + Size. Due to alignment restrictions,
1209   8-bit and 16-bit PCI configuration write cycles may be used at the beginning
1210   and the end of the range.
1211 
1212   If any reserved bits in StartAddress are set, then ASSERT().
1213   If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
1214   If Size > 0 and Buffer is NULL, then ASSERT().
1215 
1216   @param  StartAddress  Starting address that encodes the PCI Segment, Bus, Device,
1217                         Function and Register.
1218   @param  Size          Size in bytes of the transfer.
1219   @param  Buffer        Pointer to a buffer containing the data to write.
1220 
1221   @return The parameter of Size.
1222 
1223 **/
1224 UINTN
1225 EFIAPI
S3PciSegmentWriteBuffer(IN UINT64 StartAddress,IN UINTN Size,IN VOID * Buffer)1226 S3PciSegmentWriteBuffer (
1227   IN UINT64                    StartAddress,
1228   IN UINTN                     Size,
1229   IN VOID                      *Buffer
1230   )
1231 {
1232   RETURN_STATUS    Status;
1233 
1234   Status = S3BootScriptSavePciCfg2Write (
1235              S3BootScriptWidthUint8,
1236              RShiftU64 (StartAddress, 32) & 0xffff,
1237              PCI_SEGMENT_LIB_ADDRESS_TO_S3_BOOT_SCRIPT_PCI_ADDRESS (StartAddress),
1238              PciSegmentWriteBuffer (StartAddress, Size, Buffer),
1239              Buffer
1240              );
1241   ASSERT_RETURN_ERROR (Status);
1242   return Size;
1243 }
1244