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