Index: stable/10/sys/boot/efi/include/efipciio.h
===================================================================
--- stable/10/sys/boot/efi/include/efipciio.h	(nonexistent)
+++ stable/10/sys/boot/efi/include/efipciio.h	(revision 295872)
@@ -0,0 +1,557 @@
+/* $FreeBSD$ */
+/** @file
+  EFI PCI I/O Protocol provides the basic Memory, I/O, PCI configuration, 
+  and DMA interfaces that a driver uses to access its PCI controller.
+
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials                          
+  are licensed and made available under the terms and conditions of the BSD License         
+  which accompanies this distribution.  The full text of the license may be found at        
+  http://opensource.org/licenses/bsd-license.php                                            
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
+
+**/
+
+#ifndef __PCI_IO_H__
+#define __PCI_IO_H__
+
+///
+/// Global ID for the PCI I/O Protocol
+///
+#define EFI_PCI_IO_PROTOCOL_GUID \
+    { 0x4cf5b200, 0x68b8, 0x4ca5, {0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x2, 0x9a} }
+
+typedef struct _EFI_PCI_IO_PROTOCOL  EFI_PCI_IO_PROTOCOL;
+
+///
+/// *******************************************************
+/// EFI_PCI_IO_PROTOCOL_WIDTH
+/// *******************************************************
+///
+typedef enum {
+  EfiPciIoWidthUint8      = 0,
+  EfiPciIoWidthUint16,
+  EfiPciIoWidthUint32,
+  EfiPciIoWidthUint64,
+  EfiPciIoWidthFifoUint8,
+  EfiPciIoWidthFifoUint16,
+  EfiPciIoWidthFifoUint32,
+  EfiPciIoWidthFifoUint64,
+  EfiPciIoWidthFillUint8,
+  EfiPciIoWidthFillUint16,
+  EfiPciIoWidthFillUint32,
+  EfiPciIoWidthFillUint64,
+  EfiPciIoWidthMaximum
+} EFI_PCI_IO_PROTOCOL_WIDTH;
+
+//
+// Complete PCI address generater
+//
+#define EFI_PCI_IO_PASS_THROUGH_BAR               0xff    ///< Special BAR that passes a memory or I/O cycle through unchanged
+#define EFI_PCI_IO_ATTRIBUTE_MASK                 0x077f  ///< All the following I/O and Memory cycles
+#define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO   0x0001  ///< I/O cycles 0x0000-0x00FF (10 bit decode)
+#define EFI_PCI_IO_ATTRIBUTE_ISA_IO               0x0002  ///< I/O cycles 0x0100-0x03FF or greater (10 bit decode)
+#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO       0x0004  ///< I/O cycles 0x3C6, 0x3C8, 0x3C9 (10 bit decode)
+#define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY           0x0008  ///< MEM cycles 0xA0000-0xBFFFF (24 bit decode)
+#define EFI_PCI_IO_ATTRIBUTE_VGA_IO               0x0010  ///< I/O cycles 0x3B0-0x3BB and 0x3C0-0x3DF (10 bit decode)
+#define EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO       0x0020  ///< I/O cycles 0x1F0-0x1F7, 0x3F6, 0x3F7 (10 bit decode)
+#define EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO     0x0040  ///< I/O cycles 0x170-0x177, 0x376, 0x377 (10 bit decode)
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080  ///< Map a memory range so writes are combined
+#define EFI_PCI_IO_ATTRIBUTE_IO                   0x0100  ///< Enable the I/O decode bit in the PCI Config Header
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY               0x0200  ///< Enable the Memory decode bit in the PCI Config Header
+#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER           0x0400  ///< Enable the DMA bit in the PCI Config Header
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED        0x0800  ///< Map a memory range so all r/w accesses are cached
+#define EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE       0x1000  ///< Disable a memory range
+#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE      0x2000  ///< Clear for an add-in PCI Device
+#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM         0x4000  ///< Clear for a physical PCI Option ROM accessed through ROM BAR
+#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE   0x8000  ///< Clear for PCI controllers that can not genrate a DAC
+#define EFI_PCI_IO_ATTRIBUTE_ISA_IO_16            0x10000 ///< I/O cycles 0x0100-0x03FF or greater (16 bit decode)
+#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16    0x20000 ///< I/O cycles 0x3C6, 0x3C8, 0x3C9 (16 bit decode)
+#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16            0x40000 ///< I/O cycles 0x3B0-0x3BB and 0x3C0-0x3DF (16 bit decode)
+
+#define EFI_PCI_DEVICE_ENABLE                     (EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER)
+#define EFI_VGA_DEVICE_ENABLE                     (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_IO)
+
+///
+/// *******************************************************
+/// EFI_PCI_IO_PROTOCOL_OPERATION
+/// *******************************************************
+///
+typedef enum {
+  ///
+  /// A read operation from system memory by a bus master.
+  ///
+  EfiPciIoOperationBusMasterRead,
+  ///
+  /// A write operation from system memory by a bus master.
+  ///
+  EfiPciIoOperationBusMasterWrite,
+  ///
+  /// Provides both read and write access to system memory by both the processor and a
+  /// bus master. The buffer is coherent from both the processor's and the bus master's point of view.
+  ///
+  EfiPciIoOperationBusMasterCommonBuffer,
+  EfiPciIoOperationMaximum
+} EFI_PCI_IO_PROTOCOL_OPERATION;
+
+///
+/// *******************************************************
+/// EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION
+/// *******************************************************
+///
+typedef enum {
+  ///
+  /// Retrieve the PCI controller's current attributes, and return them in Result.
+  ///
+  EfiPciIoAttributeOperationGet,
+  ///
+  /// Set the PCI controller's current attributes to Attributes.
+  ///
+  EfiPciIoAttributeOperationSet,
+  ///
+  /// Enable the attributes specified by the bits that are set in Attributes for this PCI controller.
+  ///
+  EfiPciIoAttributeOperationEnable,
+  ///
+  /// Disable the attributes specified by the bits that are set in Attributes for this PCI controller.
+  ///
+  EfiPciIoAttributeOperationDisable,
+  ///
+  /// Retrieve the PCI controller's supported attributes, and return them in Result.
+  ///
+  EfiPciIoAttributeOperationSupported,
+  EfiPciIoAttributeOperationMaximum
+} EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION;
+
+/**                                                                 
+  Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is
+  satisfied or after a defined duration.                                                           
+          
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory or I/O operations.
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for the memory operation to perform.                   
+  @param  Offset                The offset within the selected BAR to start the memory operation.
+  @param  Mask                  Mask used for the polling criteria.
+  @param  Value                 The comparison value used for the polling exit criteria.
+  @param  Delay                 The number of 100 ns units to poll.
+  @param  Result                Pointer to the last value read from the memory location.
+                                
+  @retval EFI_SUCCESS           The last data returned from the access matched the poll exit criteria.
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       Offset is not valid for the BarIndex of this PCI controller.
+  @retval EFI_TIMEOUT           Delay expired before a match occurred.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+                                   
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_POLL_IO_MEM)(
+  IN EFI_PCI_IO_PROTOCOL           *This,
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH    Width,
+  IN  UINT8                        BarIndex,
+  IN  UINT64                       Offset,
+  IN  UINT64                       Mask,
+  IN  UINT64                       Value,
+  IN  UINT64                       Delay,
+  OUT UINT64                       *Result
+  );
+
+/**                                                                 
+  Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
+          
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory or I/O operations.
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for the memory or I/O operation to perform.                    
+  @param  Offset                The offset within the selected BAR to start the memory or I/O operation.                                
+  @param  Count                 The number of memory or I/O operations to perform.
+  @param  Buffer                For read operations, the destination buffer to store the results. For write
+                                operations, the source buffer to write data from.                          
+  
+  @retval EFI_SUCCESS           The data was read from or written to the PCI controller.
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI BAR specified by BarIndex.                  
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+                                   
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_IO_MEM)(
+  IN EFI_PCI_IO_PROTOCOL              *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,
+  IN     UINT8                        BarIndex,
+  IN     UINT64                       Offset,
+  IN     UINTN                        Count,
+  IN OUT VOID                         *Buffer
+  );
+
+typedef struct {
+  ///
+  /// Read PCI controller registers in the PCI memory or I/O space.
+  ///
+  EFI_PCI_IO_PROTOCOL_IO_MEM  Read;
+  ///
+  /// Write PCI controller registers in the PCI memory or I/O space.
+  ///
+  EFI_PCI_IO_PROTOCOL_IO_MEM  Write;
+} EFI_PCI_IO_PROTOCOL_ACCESS;
+
+/**                                                                 
+  Enable a PCI driver to access PCI controller registers in PCI configuration space.
+            
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.  
+  @param  Width                 Signifies the width of the memory operations.
+  @param  Offset                The offset within the PCI configuration space for the PCI controller.
+  @param  Count                 The number of PCI configuration operations to perform.
+  @param  Buffer                For read operations, the destination buffer to store the results. For write
+                                operations, the source buffer to write data from.
+  
+                                  
+  @retval EFI_SUCCESS           The data was read from or written to the PCI controller.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI configuration header of the PCI controller.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.                                 
+  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.                                
+                                     
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_CONFIG)(
+  IN EFI_PCI_IO_PROTOCOL              *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,
+  IN     UINT32                       Offset,
+  IN     UINTN                        Count,
+  IN OUT VOID                         *Buffer
+  );
+
+typedef struct {
+  ///
+  /// Read PCI controller registers in PCI configuration space.
+  ///
+  EFI_PCI_IO_PROTOCOL_CONFIG  Read;
+  ///
+  /// Write PCI controller registers in PCI configuration space.
+  ///
+  EFI_PCI_IO_PROTOCOL_CONFIG  Write;
+} EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS;
+
+/**                                                                 
+  Enables a PCI driver to copy one region of PCI memory space to another region of PCI
+  memory space.
+            
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Width                 Signifies the width of the memory operations.
+  @param  DestBarIndex          The BAR index in the standard PCI Configuration header to use as the
+                                base address for the memory operation to perform.                   
+  @param  DestOffset            The destination offset within the BAR specified by DestBarIndex to
+                                start the memory writes for the copy operation.                   
+  @param  SrcBarIndex           The BAR index in the standard PCI Configuration header to use as the
+                                base address for the memory operation to perform.                   
+  @param  SrcOffset             The source offset within the BAR specified by SrcBarIndex to start
+                                the memory reads for the copy operation.                          
+  @param  Count                 The number of memory operations to perform. Bytes moved is Width
+                                size * Count, starting at DestOffset and SrcOffset.             
+                                
+  @retval EFI_SUCCESS           The data was copied from one memory region to another memory region.
+  @retval EFI_UNSUPPORTED       DestBarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       SrcBarIndex not valid for this PCI controller.
+  @retval EFI_UNSUPPORTED       The address range specified by DestOffset, Width, and Count
+                                is not valid for the PCI BAR specified by DestBarIndex.    
+  @retval EFI_UNSUPPORTED       The address range specified by SrcOffset, Width, and Count is
+                                not valid for the PCI BAR specified by SrcBarIndex.          
+  @retval EFI_INVALID_PARAMETER Width is invalid.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+                                   
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_COPY_MEM)(
+  IN EFI_PCI_IO_PROTOCOL              *This,
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,
+  IN     UINT8                        DestBarIndex,
+  IN     UINT64                       DestOffset,
+  IN     UINT8                        SrcBarIndex,
+  IN     UINT64                       SrcOffset,
+  IN     UINTN                        Count
+  );
+
+/**                                                                 
+  Provides the PCI controller-specific addresses needed to access system memory.
+            
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Operation             Indicates if the bus master is going to read or write to system memory.
+  @param  HostAddress           The system memory address to map to the PCI controller.
+  @param  NumberOfBytes         On input the number of bytes to map. On output the number of bytes
+                                that were mapped.                                                 
+  @param  DeviceAddress         The resulting map address for the bus master PCI controller to use to
+                                access the hosts HostAddress.                                        
+  @param  Mapping               A resulting value to pass to Unmap().
+                                  
+  @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.
+  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.                                
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.
+                                   
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_MAP)(
+  IN EFI_PCI_IO_PROTOCOL                *This,
+  IN     EFI_PCI_IO_PROTOCOL_OPERATION  Operation,
+  IN     VOID                           *HostAddress,
+  IN OUT UINTN                          *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,
+  OUT    VOID                           **Mapping
+  );
+
+/**                                                                 
+  Completes the Map() operation and releases any corresponding resources.
+            
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.                                      
+  @param  Mapping               The mapping value returned from Map().
+                                  
+  @retval EFI_SUCCESS           The range was unmapped.
+  @retval EFI_DEVICE_ERROR      The data was not committed to the target system memory.
+                                   
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_UNMAP)(
+  IN EFI_PCI_IO_PROTOCOL           *This,
+  IN  VOID                         *Mapping
+  );
+
+/**                                                                 
+  Allocates pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer
+  mapping.                                                                       
+            
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.
+  @param  Type                  This parameter is not used and must be ignored.
+  @param  MemoryType            The type of memory to allocate, EfiBootServicesData or
+                                EfiRuntimeServicesData.                               
+  @param  Pages                 The number of pages to allocate.                                
+  @param  HostAddress           A pointer to store the base system memory address of the
+                                allocated range.                                        
+  @param  Attributes            The requested bit mask of attributes for the allocated range.
+                                  
+  @retval EFI_SUCCESS           The requested memory pages were allocated.
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are
+                                MEMORY_WRITE_COMBINE and MEMORY_CACHED.                     
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.  
+                                   
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_ALLOCATE_BUFFER)(
+  IN EFI_PCI_IO_PROTOCOL           *This,
+  IN  EFI_ALLOCATE_TYPE            Type,
+  IN  EFI_MEMORY_TYPE              MemoryType,
+  IN  UINTN                        Pages,
+  OUT VOID                         **HostAddress,
+  IN  UINT64                       Attributes
+  );
+
+/**                                                                 
+  Frees memory that was allocated with AllocateBuffer().
+            
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.  
+  @param  Pages                 The number of pages to free.                                
+  @param  HostAddress           The base system memory address of the allocated range.                                    
+                                  
+  @retval EFI_SUCCESS           The requested memory pages were freed.
+  @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
+                                was not allocated with AllocateBuffer().
+                                     
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_FREE_BUFFER)(
+  IN EFI_PCI_IO_PROTOCOL           *This,
+  IN  UINTN                        Pages,
+  IN  VOID                         *HostAddress
+  );
+
+/**                                                                 
+  Flushes all PCI posted write transactions from a PCI host bridge to system memory.
+            
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.  
+                                  
+  @retval EFI_SUCCESS           The PCI posted write transactions were flushed from the PCI host
+                                bridge to system memory.                                        
+  @retval EFI_DEVICE_ERROR      The PCI posted write transactions were not flushed from the PCI
+                                host bridge due to a hardware error.                           
+                                     
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_FLUSH)(
+  IN EFI_PCI_IO_PROTOCOL  *This
+  );
+
+/**                                                                 
+  Retrieves this PCI controller's current PCI bus number, device number, and function number.
+            
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.  
+  @param  SegmentNumber         The PCI controller's current PCI segment number.
+  @param  BusNumber             The PCI controller's current PCI bus number.
+  @param  DeviceNumber          The PCI controller's current PCI device number.
+  @param  FunctionNumber        The PCI controller's current PCI function number.
+                                  
+  @retval EFI_SUCCESS           The PCI controller location was returned.                                                       
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.                              
+                                     
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_GET_LOCATION)(
+  IN EFI_PCI_IO_PROTOCOL          *This,
+  OUT UINTN                       *SegmentNumber,
+  OUT UINTN                       *BusNumber,
+  OUT UINTN                       *DeviceNumber,
+  OUT UINTN                       *FunctionNumber
+  );
+
+/**                                                                 
+  Performs an operation on the attributes that this PCI controller supports. The operations include
+  getting the set of supported attributes, retrieving the current attributes, setting the current  
+  attributes, enabling attributes, and disabling attributes.                                       
+            
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.  
+  @param  Operation             The operation to perform on the attributes for this PCI controller.
+  @param  Attributes            The mask of attributes that are used for Set, Enable, and Disable
+                                operations.                                                      
+  @param  Result                A pointer to the result mask of attributes that are returned for the Get
+                                and Supported operations.                                               
+                                  
+  @retval EFI_SUCCESS           The operation on the PCI controller's attributes was completed.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.                              
+  @retval EFI_UNSUPPORTED       one or more of the bits set in                               
+                                Attributes are not supported by this PCI controller or one of
+                                its parent bridges when Operation is Set, Enable or Disable.
+                                       
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_ATTRIBUTES)(
+  IN EFI_PCI_IO_PROTOCOL                       *This,
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,
+  IN  UINT64                                   Attributes,
+  OUT UINT64                                   *Result OPTIONAL
+  );
+
+/**                                                                 
+  Gets the attributes that this PCI controller supports setting on a BAR using
+  SetBarAttributes(), and retrieves the list of resource descriptors for a BAR.
+            
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.  
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for resource range. The legal range for this field is 0..5.
+  @param  Supports              A pointer to the mask of attributes that this PCI controller supports
+                                setting for this BAR with SetBarAttributes().                        
+  @param  Resources             A pointer to the ACPI 2.0 resource descriptors that describe the current
+                                configuration of this BAR of the PCI controller.                        
+                                  
+  @retval EFI_SUCCESS           If Supports is not NULL, then the attributes that the PCI       
+                                controller supports are returned in Supports. If Resources      
+                                is not NULL, then the ACPI 2.0 resource descriptors that the PCI
+                                controller is currently using are returned in Resources.          
+  @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to allocate
+                                Resources.                                                 
+                                
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_GET_BAR_ATTRIBUTES)(
+  IN EFI_PCI_IO_PROTOCOL             *This,
+  IN  UINT8                          BarIndex,
+  OUT UINT64                         *Supports, OPTIONAL
+  OUT VOID                           **Resources OPTIONAL
+  );
+
+/**                                                                 
+  Sets the attributes for a range of a BAR on a PCI controller.
+            
+  @param  This                  A pointer to the EFI_PCI_IO_PROTOCOL instance.  
+  @param  Attributes            The mask of attributes to set for the resource range specified by
+                                BarIndex, Offset, and Length.                                    
+  @param  BarIndex              The BAR index of the standard PCI Configuration header to use as the
+                                base address for resource range. The legal range for this field is 0..5.
+  @param  Offset                A pointer to the BAR relative base address of the resource range to be
+                                modified by the attributes specified by Attributes.                   
+  @param  Length                A pointer to the length of the resource range to be modified by the
+                                attributes specified by Attributes.                                
+                                  
+  @retval EFI_SUCCESS           The set of attributes specified by Attributes for the resource      
+                                range specified by BarIndex, Offset, and Length were                
+                                set on the PCI controller, and the actual resource range is returned
+                                in Offset and Length.                                               
+  @retval EFI_INVALID_PARAMETER Offset or Length is NULL.
+  @retval EFI_UNSUPPORTED       BarIndex not valid for this PCI controller.
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources to set the attributes on the
+                                resource range specified by BarIndex, Offset, and          
+                                Length.                                                    
+                                
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PCI_IO_PROTOCOL_SET_BAR_ATTRIBUTES)(
+  IN EFI_PCI_IO_PROTOCOL              *This,
+  IN     UINT64                       Attributes,
+  IN     UINT8                        BarIndex,
+  IN OUT UINT64                       *Offset,
+  IN OUT UINT64                       *Length
+  );
+
+///
+/// The EFI_PCI_IO_PROTOCOL provides the basic Memory, I/O, PCI configuration, 
+/// and DMA interfaces used to abstract accesses to PCI controllers. 
+/// There is one EFI_PCI_IO_PROTOCOL instance for each PCI controller on a PCI bus. 
+/// A device driver that wishes to manage a PCI controller in a system will have to 
+/// retrieve the EFI_PCI_IO_PROTOCOL instance that is associated with the PCI controller. 
+///
+struct _EFI_PCI_IO_PROTOCOL {
+  EFI_PCI_IO_PROTOCOL_POLL_IO_MEM         PollMem;
+  EFI_PCI_IO_PROTOCOL_POLL_IO_MEM         PollIo;
+  EFI_PCI_IO_PROTOCOL_ACCESS              Mem;
+  EFI_PCI_IO_PROTOCOL_ACCESS              Io;
+  EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS       Pci;
+  EFI_PCI_IO_PROTOCOL_COPY_MEM            CopyMem;
+  EFI_PCI_IO_PROTOCOL_MAP                 Map;
+  EFI_PCI_IO_PROTOCOL_UNMAP               Unmap;
+  EFI_PCI_IO_PROTOCOL_ALLOCATE_BUFFER     AllocateBuffer;
+  EFI_PCI_IO_PROTOCOL_FREE_BUFFER         FreeBuffer;
+  EFI_PCI_IO_PROTOCOL_FLUSH               Flush;
+  EFI_PCI_IO_PROTOCOL_GET_LOCATION        GetLocation;
+  EFI_PCI_IO_PROTOCOL_ATTRIBUTES          Attributes;
+  EFI_PCI_IO_PROTOCOL_GET_BAR_ATTRIBUTES  GetBarAttributes;
+  EFI_PCI_IO_PROTOCOL_SET_BAR_ATTRIBUTES  SetBarAttributes;
+  
+  ///
+  /// The size, in bytes, of the ROM image.
+  ///
+  UINT64                                  RomSize;
+
+  ///
+  /// A pointer to the in memory copy of the ROM image. The PCI Bus Driver is responsible 
+  /// for allocating memory for the ROM image, and copying the contents of the ROM to memory. 
+  /// The contents of this buffer are either from the PCI option ROM that can be accessed 
+  /// through the ROM BAR of the PCI controller, or it is from a platform-specific location. 
+  /// The Attributes() function can be used to determine from which of these two sources 
+  /// the RomImage buffer was initialized.
+  /// 
+  VOID                                    *RomImage;
+};
+
+extern EFI_GUID gEfiPciIoProtocolGuid;
+
+#endif

Property changes on: stable/10/sys/boot/efi/include/efipciio.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/10/sys/boot/efi/include/efiuga.h
===================================================================
--- stable/10/sys/boot/efi/include/efiuga.h	(nonexistent)
+++ stable/10/sys/boot/efi/include/efiuga.h	(revision 295872)
@@ -0,0 +1,168 @@
+/* $FreeBSD$ */
+/** @file
+  UGA Draw protocol from the EFI 1.1 specification.
+
+  Abstraction of a very simple graphics device.
+
+  Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials are licensed and made available
+  under the terms and conditions of the BSD License which accompanies this
+  distribution.  The full text of the license may be found at:
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  File name: UgaDraw.h
+
+**/
+
+#ifndef __UGA_DRAW_H__
+#define __UGA_DRAW_H__
+
+#define EFI_UGA_DRAW_PROTOCOL_GUID \
+    { 0x982c298b, 0xf4fa, 0x41cb, {0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39} }
+
+typedef struct _EFI_UGA_DRAW_PROTOCOL EFI_UGA_DRAW_PROTOCOL;
+
+/**
+  Return the current video mode information.
+
+  @param  This                  Protocol instance pointer.
+  @param  HorizontalResolution  Current video horizontal resolution in pixels
+  @param  VerticalResolution    Current video vertical resolution in pixels
+  @param  ColorDepth            Current video color depth in bits per pixel
+  @param  RefreshRate           Current video refresh rate in Hz.
+
+  @retval EFI_SUCCESS           Mode information returned.
+  @retval EFI_NOT_STARTED       Video display is not initialized. Call SetMode ()
+  @retval EFI_INVALID_PARAMETER One of the input args was NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_UGA_DRAW_PROTOCOL_GET_MODE) (
+  IN  EFI_UGA_DRAW_PROTOCOL *This,
+  OUT UINT32                *HorizontalResolution,
+  OUT UINT32                *VerticalResolution,
+  OUT UINT32                *ColorDepth,
+  OUT UINT32                *RefreshRate
+  )
+;
+
+/**
+  Return the current video mode information.
+
+  @param  This                 Protocol instance pointer.
+  @param  HorizontalResolution Current video horizontal resolution in pixels
+  @param  VerticalResolution   Current video vertical resolution in pixels
+  @param  ColorDepth           Current video color depth in bits per pixel
+  @param  RefreshRate          Current video refresh rate in Hz.
+
+  @retval EFI_SUCCESS          Mode information returned.
+  @retval EFI_NOT_STARTED      Video display is not initialized. Call SetMode ()
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_UGA_DRAW_PROTOCOL_SET_MODE) (
+  IN  EFI_UGA_DRAW_PROTOCOL *This,
+  IN  UINT32                HorizontalResolution,
+  IN  UINT32                VerticalResolution,
+  IN  UINT32                ColorDepth,
+  IN  UINT32                RefreshRate
+  )
+;
+
+typedef struct {
+  UINT8 Blue;
+  UINT8 Green;
+  UINT8 Red;
+  UINT8 Reserved;
+} EFI_UGA_PIXEL;
+
+typedef union {
+  EFI_UGA_PIXEL Pixel;
+  UINT32        Raw;
+} EFI_UGA_PIXEL_UNION;
+
+typedef enum {
+  EfiUgaVideoFill,
+  EfiUgaVideoToBltBuffer,
+  EfiUgaBltBufferToVideo,
+  EfiUgaVideoToVideo,
+  EfiUgaBltMax
+} EFI_UGA_BLT_OPERATION;
+
+/**
+  Type specifying a pointer to a function to perform an UGA Blt operation.
+
+    The following table defines actions for BltOperations:
+
+    <B>EfiUgaVideoFill</B> - Write data from the  BltBuffer pixel (SourceX, SourceY) 
+      directly to every pixel of the video display rectangle 
+      (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). 
+      Only one pixel will be used from the BltBuffer. Delta is NOT used.
+
+    <B>EfiUgaVideoToBltBuffer</B> - Read data from the video display rectangle 
+      (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in 
+      the BltBuffer rectangle (DestinationX, DestinationY ) 
+      (DestinationX + Width, DestinationY + Height). If DestinationX or 
+      DestinationY is not zero then Delta must be set to the length in bytes 
+      of a row in the BltBuffer.
+
+    <B>EfiUgaBltBufferToVideo</B> - Write data from the  BltBuffer rectangle 
+      (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the 
+      video display rectangle (DestinationX, DestinationY) 
+      (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is 
+      not zero then Delta must be set to the length in bytes of a row in the 
+      BltBuffer.
+
+    <B>EfiUgaVideoToVideo</B> - Copy from the video display rectangle (SourceX, SourceY)
+     (SourceX + Width, SourceY + Height) .to the video display rectangle 
+     (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). 
+     The BltBuffer and Delta  are not used in this mode.
+
+
+    @param[in] This          - Protocol instance pointer.
+    @param[in] BltBuffer     - Buffer containing data to blit into video buffer. This 
+                               buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
+    @param[in] BltOperation  - Operation to perform on BlitBuffer and video memory
+    @param[in] SourceX       - X coordinate of source for the BltBuffer.
+    @param[in] SourceY       - Y coordinate of source for the BltBuffer.
+    @param[in] DestinationX  - X coordinate of destination for the BltBuffer.
+    @param[in] DestinationY  - Y coordinate of destination for the BltBuffer.
+    @param[in] Width         - Width of rectangle in BltBuffer in pixels.
+    @param[in] Height        - Hight of rectangle in BltBuffer in pixels.
+    @param[in] Delta         - OPTIONAL
+  
+    @retval EFI_SUCCESS           - The Blt operation completed.
+    @retval EFI_INVALID_PARAMETER - BltOperation is not valid.
+    @retval EFI_DEVICE_ERROR      - A hardware error occured writting to the video buffer.
+
+--*/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_UGA_DRAW_PROTOCOL_BLT) (
+  IN  EFI_UGA_DRAW_PROTOCOL                   * This,
+  IN  EFI_UGA_PIXEL                           * BltBuffer, OPTIONAL
+  IN  EFI_UGA_BLT_OPERATION                   BltOperation,
+  IN  UINTN                                   SourceX,
+  IN  UINTN                                   SourceY,
+  IN  UINTN                                   DestinationX,
+  IN  UINTN                                   DestinationY,
+  IN  UINTN                                   Width,
+  IN  UINTN                                   Height,
+  IN  UINTN                                   Delta         OPTIONAL
+  );
+
+struct _EFI_UGA_DRAW_PROTOCOL {
+  EFI_UGA_DRAW_PROTOCOL_GET_MODE  GetMode;
+  EFI_UGA_DRAW_PROTOCOL_SET_MODE  SetMode;
+  EFI_UGA_DRAW_PROTOCOL_BLT       Blt;
+};
+
+extern EFI_GUID gEfiUgaDrawProtocolGuid;
+
+#endif

Property changes on: stable/10/sys/boot/efi/include/efiuga.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/10/sys/boot/efi/loader/arch/amd64/framebuffer.c
===================================================================
--- stable/10/sys/boot/efi/loader/arch/amd64/framebuffer.c	(revision 295871)
+++ stable/10/sys/boot/efi/loader/arch/amd64/framebuffer.c	(revision 295872)
@@ -1,87 +1,566 @@
 /*-
  * Copyright (c) 2013 The FreeBSD Foundation
  * All rights reserved.
  *
  * This software was developed by Benno Rice under sponsorship from
  * the FreeBSD Foundation.
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <bootstrap.h>
+#include <sys/endian.h>
 #include <stand.h>
 
 #include <efi.h>
 #include <efilib.h>
+#include <efiuga.h>
+#include <efipciio.h>
 #include <machine/metadata.h>
 
 #include "framebuffer.h"
 
 static EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+static EFI_GUID pciio_guid = EFI_PCI_IO_PROTOCOL_GUID;
+static EFI_GUID uga_guid = EFI_UGA_DRAW_PROTOCOL_GUID;
 
-int
-efi_find_framebuffer(struct efi_fb *efifb)
+static u_int
+efifb_color_depth(struct efi_fb *efifb)
 {
-	EFI_GRAPHICS_OUTPUT			*gop;
-	EFI_STATUS				status;
-	EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE	*mode;
-	EFI_GRAPHICS_OUTPUT_MODE_INFORMATION	*info;
+	uint32_t mask;
+	u_int depth;
 
-	status = BS->LocateProtocol(&gop_guid, NULL, (VOID **)&gop);
-	if (EFI_ERROR(status))
-		return (1);
+	mask = efifb->fb_mask_red | efifb->fb_mask_green |
+	    efifb->fb_mask_blue | efifb->fb_mask_reserved;
+	if (mask == 0)
+		return (0);
+	for (depth = 1; mask != 1; depth++)
+		mask >>= 1;
+	return (depth);
+}
 
-	mode = gop->Mode;
-	info = gop->Mode->Info;
+static int
+efifb_mask_from_pixfmt(struct efi_fb *efifb, EFI_GRAPHICS_PIXEL_FORMAT pixfmt,
+    EFI_PIXEL_BITMASK *pixinfo)
+{
+	int result;
 
-	efifb->fb_addr = mode->FrameBufferBase;
-	efifb->fb_size = mode->FrameBufferSize;
-	efifb->fb_height = info->VerticalResolution;
-	efifb->fb_width = info->HorizontalResolution;
-	efifb->fb_stride = info->PixelsPerScanLine;
-
-	switch (info->PixelFormat) {
+	result = 0;
+	switch (pixfmt) {
 	case PixelRedGreenBlueReserved8BitPerColor:
 		efifb->fb_mask_red = 0x000000ff;
 		efifb->fb_mask_green = 0x0000ff00;
 		efifb->fb_mask_blue = 0x00ff0000;
 		efifb->fb_mask_reserved = 0xff000000;
 		break;
 	case PixelBlueGreenRedReserved8BitPerColor:
 		efifb->fb_mask_red = 0x00ff0000;
 		efifb->fb_mask_green = 0x0000ff00;
 		efifb->fb_mask_blue = 0x000000ff;
 		efifb->fb_mask_reserved = 0xff000000;
 		break;
 	case PixelBitMask:
-		efifb->fb_mask_red = info->PixelInformation.RedMask;
-		efifb->fb_mask_green = info->PixelInformation.GreenMask;
-		efifb->fb_mask_blue = info->PixelInformation.BlueMask;
-		efifb->fb_mask_reserved =
-		    info->PixelInformation.ReservedMask;
+		efifb->fb_mask_red = pixinfo->RedMask;
+		efifb->fb_mask_green = pixinfo->GreenMask;
+		efifb->fb_mask_blue = pixinfo->BlueMask;
+		efifb->fb_mask_reserved = pixinfo->ReservedMask;
 		break;
 	default:
+		result = 1;
+		break;
+	}
+	return (result);
+}
+
+static int
+efifb_from_gop(struct efi_fb *efifb, EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *mode,
+    EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info)
+{
+	int result;
+
+	efifb->fb_addr = mode->FrameBufferBase;
+	efifb->fb_size = mode->FrameBufferSize;
+	efifb->fb_height = info->VerticalResolution;
+	efifb->fb_width = info->HorizontalResolution;
+	efifb->fb_stride = info->PixelsPerScanLine;
+	result = efifb_mask_from_pixfmt(efifb, info->PixelFormat,
+	    &info->PixelInformation);
+	return (result);
+}
+
+static ssize_t
+efifb_uga_find_pixel(EFI_UGA_DRAW_PROTOCOL *uga, u_int line,
+    EFI_PCI_IO_PROTOCOL *pciio, uint64_t addr, uint64_t size)
+{
+	EFI_UGA_PIXEL pix0, pix1;
+	uint8_t *data1, *data2;
+	size_t count, maxcount = 1024;
+	ssize_t ofs;
+	EFI_STATUS status;
+	u_int idx;
+
+	status = uga->Blt(uga, &pix0, EfiUgaVideoToBltBuffer,
+	    0, line, 0, 0, 1, 1, 0);
+	if (EFI_ERROR(status)) {
+		printf("UGA BLT operation failed (video->buffer)");
+		return (-1);
+	}
+	pix1.Red = ~pix0.Red;
+	pix1.Green = ~pix0.Green;
+	pix1.Blue = ~pix0.Blue;
+	pix1.Reserved = 0;
+
+	data1 = calloc(maxcount, 2);
+	if (data1 == NULL) {
+		printf("Unable to allocate memory");
+		return (-1);
+	}
+	data2 = data1 + maxcount;
+
+	ofs = 0;
+	while (size > 0) {
+		count = min(size, maxcount);
+
+		status = pciio->Mem.Read(pciio, EfiPciIoWidthUint32,
+		    EFI_PCI_IO_PASS_THROUGH_BAR, addr + ofs, count >> 2,
+		    data1);
+		if (EFI_ERROR(status)) {
+			printf("Error reading frame buffer (before)");
+			goto fail;
+		}
+		status = uga->Blt(uga, &pix1, EfiUgaBltBufferToVideo,
+		    0, 0, 0, line, 1, 1, 0);
+		if (EFI_ERROR(status)) {
+			printf("UGA BLT operation failed (modify)");
+			goto fail;
+		}
+		status = pciio->Mem.Read(pciio, EfiPciIoWidthUint32,
+		    EFI_PCI_IO_PASS_THROUGH_BAR, addr + ofs, count >> 2,
+		    data2);
+		if (EFI_ERROR(status)) {
+			printf("Error reading frame buffer (after)");
+			goto fail;
+		}
+		status = uga->Blt(uga, &pix0, EfiUgaBltBufferToVideo,
+		    0, 0, 0, line, 1, 1, 0);
+		if (EFI_ERROR(status)) {
+			printf("UGA BLT operation failed (restore)");
+			goto fail;
+		}
+		for (idx = 0; idx < count; idx++) {
+			if (data1[idx] != data2[idx]) {
+				free(data1);
+				return (ofs + (idx & ~3));
+			}
+		}
+		ofs += count;
+		size -= count;
+	}
+	printf("No change detected in frame buffer");
+
+ fail:
+	printf(" -- error %lu\n", status & ~EFI_ERROR_MASK);
+	free(data1);
+	return (-1);
+}
+
+static EFI_PCI_IO_PROTOCOL *
+efifb_uga_get_pciio(void)
+{
+	EFI_PCI_IO_PROTOCOL *pciio;
+	EFI_HANDLE *buf, *hp;
+	EFI_STATUS status;
+	UINTN bufsz;
+
+	/* Get all handles that support the UGA protocol. */
+	bufsz = 0;
+	status = BS->LocateHandle(ByProtocol, &uga_guid, NULL, &bufsz, NULL);
+	if (status != EFI_BUFFER_TOO_SMALL)
+		return (NULL);
+	buf = malloc(bufsz);
+	status = BS->LocateHandle(ByProtocol, &uga_guid, NULL, &bufsz, buf);
+	if (status != EFI_SUCCESS) {
+		free(buf);
+		return (NULL);
+	}
+	bufsz /= sizeof(EFI_HANDLE);
+
+	/* Get the PCI I/O interface of the first handle that supports it. */
+	pciio = NULL;
+	for (hp = buf; hp < buf + bufsz; hp++) {
+		status = BS->HandleProtocol(*hp, &pciio_guid, (void **)&pciio);
+		if (status == EFI_SUCCESS) {
+			free(buf);
+			return (pciio);
+		}
+	}
+	free(buf);
+	return (NULL);
+}
+
+static EFI_STATUS
+efifb_uga_locate_framebuffer(EFI_PCI_IO_PROTOCOL *pciio, uint64_t *addrp,
+    uint64_t *sizep)
+{
+	uint8_t *resattr;
+	uint64_t addr, size;
+	EFI_STATUS status;
+	u_int bar;
+
+	if (pciio == NULL)
+		return (EFI_DEVICE_ERROR);
+
+	/* Attempt to get the frame buffer address (imprecise). */
+	*addrp = 0;
+	*sizep = 0;
+	for (bar = 0; bar < 6; bar++) {
+		status = pciio->GetBarAttributes(pciio, bar, NULL,
+		    (void **)&resattr);
+		if (status != EFI_SUCCESS)
+			continue;
+		/* XXX magic offsets and constants. */
+		if (resattr[0] == 0x87 && resattr[3] == 0) {
+			/* 32-bit address space descriptor (MEMIO) */
+			addr = le32dec(resattr + 10);
+			size = le32dec(resattr + 22);
+		} else if (resattr[0] == 0x8a && resattr[3] == 0) {
+			/* 64-bit address space descriptor (MEMIO) */
+			addr = le64dec(resattr + 14);
+			size = le64dec(resattr + 38);
+		} else {
+			addr = 0;
+			size = 0;
+		}
+		BS->FreePool(resattr);
+		if (addr == 0 || size == 0)
+			continue;
+
+		/* We assume the largest BAR is the frame buffer. */
+		if (size > *sizep) {
+			*addrp = addr;
+			*sizep = size;
+		}
+	}
+	return ((*addrp == 0 || *sizep == 0) ? EFI_DEVICE_ERROR : 0);
+}
+
+static int
+efifb_from_uga(struct efi_fb *efifb, EFI_UGA_DRAW_PROTOCOL *uga)
+{
+	EFI_PCI_IO_PROTOCOL *pciio;
+	char *ev, *p;
+	EFI_STATUS status;
+	ssize_t offset;
+	uint64_t fbaddr;
+	uint32_t horiz, vert, stride;
+	uint32_t np, depth, refresh;
+
+	status = uga->GetMode(uga, &horiz, &vert, &depth, &refresh);
+	if (EFI_ERROR(status))
 		return (1);
+	efifb->fb_height = vert;
+	efifb->fb_width = horiz;
+	/* Paranoia... */
+	if (efifb->fb_height == 0 || efifb->fb_width == 0)
+		return (1);
+
+	/* The color masks are fixed AFAICT. */
+	efifb_mask_from_pixfmt(efifb, PixelBlueGreenRedReserved8BitPerColor,
+	    NULL);
+
+	/* pciio can be NULL on return! */
+	pciio = efifb_uga_get_pciio();
+
+	/* Try to find the frame buffer. */
+	status = efifb_uga_locate_framebuffer(pciio, &efifb->fb_addr,
+	    &efifb->fb_size);
+	if (EFI_ERROR(status)) {
+		efifb->fb_addr = 0;
+		efifb->fb_size = 0;
 	}
+
+	/*
+	 * There's no reliable way to detect the frame buffer or the
+	 * offset within the frame buffer of the visible region, nor
+	 * the stride. Our only option is to look at the system and
+	 * fill in the blanks based on that. Luckily, UGA was mostly
+	 * only used on Apple hardware. 
+	 */
+	offset = -1;
+	ev = getenv("smbios.system.maker");
+	if (ev != NULL && !strcmp(ev, "Apple Inc.")) {
+		ev = getenv("smbios.system.product");
+		if (ev != NULL && !strcmp(ev, "iMac7,1")) {
+			/* These are the expected values we should have. */
+			horiz = 1680;
+			vert = 1050;
+			fbaddr = 0xc0000000;
+			/* These are the missing bits. */
+			offset = 0x10000;
+			stride = 1728;
+		} else if (ev != NULL && !strcmp(ev, "MacBook3,1")) {
+			/* These are the expected values we should have. */
+			horiz = 1280;
+			vert = 800;
+			fbaddr = 0xc0000000;
+			/* These are the missing bits. */
+			offset = 0x0;
+			stride = 2048;
+		}
+	}
+
+	/*
+	 * If this is hardware we know, make sure that it looks familiar
+	 * before we accept our hardcoded values.
+	 */
+	if (offset >= 0 && efifb->fb_width == horiz &&
+	    efifb->fb_height == vert && efifb->fb_addr == fbaddr) {
+		efifb->fb_addr += offset;
+		efifb->fb_size -= offset;
+		efifb->fb_stride = stride;
+		return (0);
+	} else if (offset >= 0) {
+		printf("Hardware make/model known, but graphics not "
+		    "as expected.\n");
+		printf("Console may not work!\n");
+	}
+
+	/*
+	 * The stride is equal or larger to the width. Often it's the
+	 * next larger power of two. We'll start with that...
+	 */
+	efifb->fb_stride = efifb->fb_width;
+	do {
+		np = efifb->fb_stride & (efifb->fb_stride - 1);
+		if (np) {
+			efifb->fb_stride |= (np - 1);
+			efifb->fb_stride++;
+		}
+	} while (np);
+
+	ev = getenv("hw.efifb.address");
+	if (ev == NULL) {
+		if (efifb->fb_addr == 0) {
+			printf("Please set hw.efifb.address and "
+			    "hw.efifb.stride.\n");
+			return (1);
+		}
+
+		/*
+		 * The visible part of the frame buffer may not start at
+		 * offset 0, so try to detect it. Note that we may not
+		 * always be able to read from the frame buffer, which
+		 * means that we may not be able to detect anything. In
+		 * that case, we would take a long time scanning for a
+		 * pixel change in the frame buffer, which would have it
+		 * appear that we're hanging, so we limit the scan to
+		 * 1/256th of the frame buffer. This number is mostly
+		 * based on PR 202730 and the fact that on a MacBoook,
+		 * where we can't read from the frame buffer the offset
+		 * of the visible region is 0. In short: we want to scan
+		 * enough to handle all adapters that have an offset
+		 * larger than 0 and we want to scan as little as we can
+		 * to not appear to hang when we can't read from the
+		 * frame buffer.
+		 */
+		offset = efifb_uga_find_pixel(uga, 0, pciio, efifb->fb_addr,
+		    efifb->fb_size >> 8);
+		if (offset == -1) {
+			printf("Unable to reliably detect frame buffer.\n");
+		} else if (offset > 0) {
+			efifb->fb_addr += offset;
+			efifb->fb_size -= offset;
+		}
+	} else {
+		offset = 0;
+		efifb->fb_size = efifb->fb_height * efifb->fb_stride * 4;
+		efifb->fb_addr = strtoul(ev, &p, 0);
+		if (*p != '\0')
+			return (1);
+	}
+
+	ev = getenv("hw.efifb.stride");
+	if (ev == NULL) {
+		if (pciio != NULL && offset != -1) {
+			/* Determine the stride. */
+			offset = efifb_uga_find_pixel(uga, 1, pciio,
+			    efifb->fb_addr, horiz * 8);
+			if (offset != -1)
+				efifb->fb_stride = offset >> 2;
+		} else {
+			printf("Unable to reliably detect the stride.\n");
+		}
+	} else {
+		efifb->fb_stride = strtoul(ev, &p, 0);
+		if (*p != '\0')
+			return (1);
+	}
+
+	/*
+	 * We finalized on the stride, so recalculate the size of the
+	 * frame buffer.
+	 */
+	efifb->fb_size = efifb->fb_height * efifb->fb_stride * 4;
 	return (0);
+}
+
+int
+efi_find_framebuffer(struct efi_fb *efifb)
+{
+	EFI_GRAPHICS_OUTPUT *gop;
+	EFI_UGA_DRAW_PROTOCOL *uga;
+	EFI_STATUS status;
+
+	status = BS->LocateProtocol(&gop_guid, NULL, (VOID **)&gop);
+	if (status == EFI_SUCCESS)
+		return (efifb_from_gop(efifb, gop->Mode, gop->Mode->Info));
+
+	status = BS->LocateProtocol(&uga_guid, NULL, (VOID **)&uga);
+	if (status == EFI_SUCCESS)
+		return (efifb_from_uga(efifb, uga));
+
+	return (1);
+}
+
+static void
+print_efifb(int mode, struct efi_fb *efifb, int verbose)
+{
+	u_int depth;
+
+	if (mode >= 0)
+		printf("mode %d: ", mode);
+	depth = efifb_color_depth(efifb);
+	printf("%ux%ux%u, stride=%u", efifb->fb_width, efifb->fb_height,
+	    depth, efifb->fb_stride);
+	if (verbose) {
+		printf("\n    frame buffer: address=%jx, size=%jx",
+		    (uintmax_t)efifb->fb_addr, (uintmax_t)efifb->fb_size);
+		printf("\n    color mask: R=%08x, G=%08x, B=%08x\n",
+		    efifb->fb_mask_red, efifb->fb_mask_green,
+		    efifb->fb_mask_blue);
+	}
+}
+
+COMMAND_SET(gop, "gop", "graphics output protocol", command_gop);
+
+static int
+command_gop(int argc, char *argv[])
+{
+	struct efi_fb efifb;
+	EFI_GRAPHICS_OUTPUT *gop;
+	EFI_STATUS status;
+	u_int mode;
+
+	status = BS->LocateProtocol(&gop_guid, NULL, (VOID **)&gop);
+	if (EFI_ERROR(status)) {
+		sprintf(command_errbuf, "%s: Graphics Output Protocol not "
+		    "present (error=%lu)", argv[0], status & ~EFI_ERROR_MASK);
+		return (CMD_ERROR);
+	}
+
+	if (argc < 2)
+		goto usage;
+
+	if (!strcmp(argv[1], "set")) {
+		char *cp;
+
+		if (argc != 3)
+			goto usage;
+		mode = strtol(argv[2], &cp, 0);
+		if (cp[0] != '\0') {
+			sprintf(command_errbuf, "mode is an integer");
+			return (CMD_ERROR);
+		}
+		status = gop->SetMode(gop, mode);
+		if (EFI_ERROR(status)) {
+			sprintf(command_errbuf, "%s: Unable to set mode to "
+			    "%u (error=%lu)", argv[0], mode,
+			    status & ~EFI_ERROR_MASK);
+			return (CMD_ERROR);
+		}
+	} else if (!strcmp(argv[1], "get")) {
+		if (argc != 2)
+			goto usage;
+		efifb_from_gop(&efifb, gop->Mode, gop->Mode->Info);
+		print_efifb(gop->Mode->Mode, &efifb, 1);
+		printf("\n");
+	} else if (!strcmp(argv[1], "list")) {
+		EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
+		UINTN infosz;
+
+		if (argc != 2)
+			goto usage;
+		pager_open();
+		for (mode = 0; mode < gop->Mode->MaxMode; mode++) {
+			status = gop->QueryMode(gop, mode, &infosz, &info);
+			if (EFI_ERROR(status))
+				continue;
+			efifb_from_gop(&efifb, gop->Mode, info);
+			print_efifb(mode, &efifb, 0);
+			if (pager_output("\n"))
+				break;
+		}
+		pager_close();
+	}
+	return (CMD_OK);
+
+ usage:
+	sprintf(command_errbuf, "usage: %s [list | get | set <mode>]",
+	    argv[0]);
+	return (CMD_ERROR);
+}
+
+COMMAND_SET(uga, "uga", "universal graphics adapter", command_uga);
+
+static int
+command_uga(int argc, char *argv[])
+{
+	struct efi_fb efifb;
+	EFI_UGA_DRAW_PROTOCOL *uga;
+	EFI_STATUS status;
+
+	status = BS->LocateProtocol(&uga_guid, NULL, (VOID **)&uga);
+	if (EFI_ERROR(status)) {
+		sprintf(command_errbuf, "%s: UGA Protocol not present "
+		    "(error=%lu)", argv[0], status & ~EFI_ERROR_MASK);
+		return (CMD_ERROR);
+	}
+
+	if (argc != 1)
+		goto usage;
+
+	if (efifb_from_uga(&efifb, uga) != CMD_OK) {
+		sprintf(command_errbuf, "%s: Unable to get UGA information",
+		    argv[0]);
+		return (CMD_ERROR);
+	}
+
+	print_efifb(-1, &efifb, 1);
+	printf("\n");
+	return (CMD_OK);
+
+ usage:
+	sprintf(command_errbuf, "usage: %s", argv[0]);
+	return (CMD_ERROR);
 }
Index: stable/10
===================================================================
--- stable/10	(revision 295871)
+++ stable/10	(revision 295872)

Property changes on: stable/10
___________________________________________________________________
Modified: svn:mergeinfo
## -0,0 +0,1 ##
   Merged /head:r287299,287317,287422,287475,287489,287538