source: bootcd/isolinux/syslinux-6.03/gnu-efi/gnu-efi-3.0/apps/route80h.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 3.3 KB
RevLine 
[e16e8f2]1#include <efi.h>
2#include <efilib.h>
3
4/* this example program changes the Reserved Page Route (RPR) bit on ICH10's General
5 * Control And Status Register (GCS) from LPC to PCI.  In practical terms, it routes
6 * outb to port 80h to the PCI bus. */
7
8#define GCS_OFFSET_ADDR 0x3410
9#define GCS_RPR_SHIFT 2
10#define GCS_RPR_PCI 1
11#define GCS_RPR_LPC 0
12
13#define VENDOR_ID_INTEL 0x8086
14#define DEVICE_ID_LPCIF 0x3a16
15#define DEVICE_ID_COUGARPOINT_LPCIF 0x1c56
16
17static EFI_HANDLE ImageHandle;
18
19typedef struct {
20        uint16_t vendor_id;     /* 00-01 */
21        uint16_t device_id;     /* 02-03 */
22        char pad[0xEB];         /* 04-EF */
23        uint32_t rcba;          /* F0-F3 */
24        uint32_t reserved[3];   /* F4-FF */
25} lpcif_t;
26
27static inline void set_bit(volatile uint32_t *flag, int bit, int value)
28{
29        uint32_t val = *flag;
30        Print(L"current value is 0x%2x\n", val);
31
32        if (value) {
33                val |= (1 << bit);
34        } else {
35                val &= ~(1 << bit);
36        }
37        Print(L"setting value to 0x%2x\n", val);
38        *flag = val;
39        val = *flag;
40        Print(L"new value is 0x%2x\n", val);
41}
42
43static inline int configspace_matches_ids(void *config, uint32_t vendor_id,
44                                uint32_t device_id)
45{
46        uint32_t *cfg = config;
47        if (cfg[0] == vendor_id && cfg[1] == device_id)
48                return 1;
49        return 0;
50}
51
52static int is_device(EFI_PCI_IO *pciio, uint16_t vendor_id, uint16_t device_id)
53{
54        lpcif_t lpcif;
55        EFI_STATUS rc;
56
57        rc = uefi_call_wrapper(pciio->Pci.Read, 5, pciio, EfiPciIoWidthUint16, 0, 2, &lpcif);
58        if (EFI_ERROR(rc))
59                return 0;
60
61        if (vendor_id == lpcif.vendor_id && device_id == lpcif.device_id)
62                return 1;
63        return 0;
64}
65
66static EFI_STATUS find_pci_device(uint16_t vendor_id, uint16_t device_id,
67                                EFI_PCI_IO **pciio)
68{
69        EFI_STATUS rc;
70        EFI_HANDLE *Handles;
71        UINTN NoHandles;
72        int i;
73
74        if (!pciio)
75                return EFI_INVALID_PARAMETER;
76
77        rc = LibLocateHandle(ByProtocol, &PciIoProtocol, NULL, &NoHandles,
78                             &Handles);
79        if (EFI_ERROR(rc))
80                return rc;
81
82        for (i = 0; i < NoHandles; i++) {
83                void *pciio_tmp = NULL;
84                rc = uefi_call_wrapper(BS->OpenProtocol, 6, Handles[i],
85                                    &PciIoProtocol, &pciio_tmp, ImageHandle,
86                                    NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
87                if (EFI_ERROR(rc))
88                        continue;
89                *pciio = pciio_tmp;
90                if (!is_device(*pciio, vendor_id, device_id)) {
91                        *pciio = NULL;
92                        continue;
93                }
94
95                return EFI_SUCCESS;
96        }
97        return EFI_NOT_FOUND;
98}
99
100EFI_STATUS
101efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab)
102{
103        InitializeLib(image_handle, systab);
104        EFI_PCI_IO *pciio = NULL;
105        lpcif_t lpcif;
106        EFI_STATUS rc;
107        struct {
108                uint16_t vendor;
109                uint16_t device;
110        } devices[] = {
111                { VENDOR_ID_INTEL, DEVICE_ID_LPCIF },
112                { VENDOR_ID_INTEL, DEVICE_ID_COUGARPOINT_LPCIF },
113                { 0, 0 }
114        };
115        int i;
116
117        ImageHandle = image_handle;
118        for (i = 0; devices[i].vendor != 0; i++) {
119                rc = find_pci_device(devices[i].vendor, devices[i].device, &pciio);
120                if (EFI_ERROR(rc))
121                        continue;
122        }
123
124        if (rc == EFI_NOT_FOUND) {
125                Print(L"Device not found.\n");
126                return rc;
127        } else if (EFI_ERROR(rc)) {
128                return rc;
129        }
130
131        rc = uefi_call_wrapper(pciio->Pci.Read, 5, pciio, EfiPciIoWidthUint32,
132                EFI_FIELD_OFFSET(lpcif_t, rcba), 1, &lpcif.rcba);
133        if (EFI_ERROR(rc))
134                return rc;
135        if (!(lpcif.rcba & 1)) {
136                Print(L"rcrb is not mapped, cannot route port 80h\n");
137                return EFI_UNSUPPORTED;
138        }
139        lpcif.rcba &= ~1UL;
140
141        Print(L"rcba: 0x%8x\n", lpcif.rcba, lpcif.rcba);
142        set_bit((uint32_t *)(uint64_t)(lpcif.rcba + GCS_OFFSET_ADDR),
143                     GCS_RPR_SHIFT, GCS_RPR_PCI);
144
145        return EFI_SUCCESS;
146}
Note: See TracBrowser for help on using the repository browser.