160 lines
4.1 KiB
Diff
160 lines
4.1 KiB
Diff
From 796ce7f03ed606a801b6a23384e8cf4a13c46fc6 Mon Sep 17 00:00:00 2001
|
|
From: Peter Jones <pjones@redhat.com>
|
|
Date: Mon, 26 Jul 2010 17:04:12 -0400
|
|
Subject: [PATCH] Add the "route80h.efi" test program.
|
|
|
|
This is a test program for PciIo. It routes port80h on ICH10 to PCI.
|
|
---
|
|
apps/Makefile | 2 +-
|
|
apps/route80h.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
2 files changed, 126 insertions(+), 1 deletions(-)
|
|
create mode 100644 apps/route80h.c
|
|
|
|
diff --git a/apps/Makefile b/apps/Makefile
|
|
index 44122ad..2baf64d 100644
|
|
--- a/apps/Makefile
|
|
+++ b/apps/Makefile
|
|
@@ -38,7 +38,7 @@ LDFLAGS += -T $(LDSCRIPT) -shared -Bsymbolic -L../lib -L../gnuefi $(CRTOBJS)
|
|
LOADLIBES = -lefi -lgnuefi $(shell $(CC) $(ARCH3264) -print-libgcc-file-name)
|
|
FORMAT = efi-app-$(ARCH)
|
|
|
|
-TARGETS = t.efi t2.efi t3.efi t4.efi t5.efi t6.efi printenv.efi t7.efi
|
|
+TARGETS = t.efi t2.efi t3.efi t4.efi t5.efi t6.efi printenv.efi t7.efi route80h.efi
|
|
|
|
all: $(TARGETS)
|
|
|
|
diff --git a/apps/route80h.c b/apps/route80h.c
|
|
new file mode 100644
|
|
index 0000000..05cc883
|
|
--- /dev/null
|
|
+++ b/apps/route80h.c
|
|
@@ -0,0 +1,125 @@
|
|
+#include <efi.h>
|
|
+#include <efilib.h>
|
|
+
|
|
+/* this example program changes the Reserved Page Route (RPR) bit on ICH10's General
|
|
+ * Control And Status Register (GCS) from LPC to PCI. In practical terms, it routes
|
|
+ * outb to port 80h to the PCI bus. */
|
|
+
|
|
+#define GCS_OFFSET_ADDR 0x3410
|
|
+#define GCS_RPR_SHIFT 2
|
|
+#define GCS_RPR_PCI 1
|
|
+#define GCS_RPR_LPC 0
|
|
+
|
|
+#define VENDOR_ID_INTEL 0x8086
|
|
+#define DEVICE_ID_LPCIF 0x3a16
|
|
+
|
|
+static EFI_HANDLE ImageHandle;
|
|
+
|
|
+typedef struct {
|
|
+ uint16_t vendor_id; /* 00-01 */
|
|
+ uint16_t device_id; /* 02-03 */
|
|
+ char pad[0xEB]; /* 04-EF */
|
|
+ uint32_t rcba; /* F0-F3 */
|
|
+ uint32_t reserved[3]; /* F4-FF */
|
|
+} lpcif_t;
|
|
+
|
|
+static inline void set_bit(volatile uint32_t *flag, int bit, int value)
|
|
+{
|
|
+ uint32_t val = *flag;
|
|
+ Print(L"current value is 0x%2x\n", val);
|
|
+
|
|
+ if (value) {
|
|
+ val |= (1 << bit);
|
|
+ } else {
|
|
+ val &= ~(1 << bit);
|
|
+ }
|
|
+ Print(L"setting value to 0x%2x\n", val);
|
|
+ *flag = val;
|
|
+ val = *flag;
|
|
+ Print(L"new value is 0x%2x\n", val);
|
|
+}
|
|
+
|
|
+static inline int configspace_matches_ids(void *config, uint32_t vendor_id,
|
|
+ uint32_t device_id)
|
|
+{
|
|
+ uint32_t *cfg = config;
|
|
+ if (cfg[0] == vendor_id && cfg[1] == device_id)
|
|
+ return 1;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int is_device(EFI_PCI_IO *pciio, uint16_t vendor_id, uint16_t device_id)
|
|
+{
|
|
+ lpcif_t lpcif;
|
|
+ EFI_STATUS rc;
|
|
+
|
|
+ rc = uefi_call_wrapper(pciio->Pci.Read, 5, pciio, EfiPciIoWidthUint16, 0, 2, &lpcif);
|
|
+ if (EFI_ERROR(rc))
|
|
+ return 0;
|
|
+
|
|
+ if (vendor_id == lpcif.vendor_id && device_id == lpcif.device_id)
|
|
+ return 1;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static EFI_STATUS find_pci_device(uint16_t vendor_id, uint16_t device_id,
|
|
+ EFI_PCI_IO **pciio)
|
|
+{
|
|
+ EFI_STATUS rc;
|
|
+ EFI_HANDLE *Handles;
|
|
+ UINTN NoHandles;
|
|
+ int i;
|
|
+
|
|
+ rc = LibLocateHandle(ByProtocol, &PciIoProtocol, NULL, &NoHandles,
|
|
+ &Handles);
|
|
+ if (EFI_ERROR(rc))
|
|
+ return rc;
|
|
+
|
|
+ for (i = 0; i < NoHandles; i++) {
|
|
+ rc = uefi_call_wrapper(BS->OpenProtocol, 6, Handles[i],
|
|
+ &PciIoProtocol, pciio, ImageHandle,
|
|
+ NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
|
+ if (EFI_ERROR(rc))
|
|
+ continue;
|
|
+ if (!is_device(*pciio, vendor_id, device_id))
|
|
+ continue;
|
|
+
|
|
+ return EFI_SUCCESS;
|
|
+ }
|
|
+ return EFI_NOT_FOUND;
|
|
+}
|
|
+
|
|
+EFI_STATUS
|
|
+efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab)
|
|
+{
|
|
+ InitializeLib(image_handle, systab);
|
|
+ EFI_PCI_IO *pciio;
|
|
+ lpcif_t lpcif;
|
|
+ EFI_STATUS rc;
|
|
+
|
|
+ ImageHandle = image_handle;
|
|
+ rc = find_pci_device(VENDOR_ID_INTEL, DEVICE_ID_LPCIF, &pciio);
|
|
+
|
|
+ if (rc == EFI_NOT_FOUND) {
|
|
+ Print(L"Device not found.\n");
|
|
+ return rc;
|
|
+ } else if (EFI_ERROR(rc)) {
|
|
+ return rc;
|
|
+ }
|
|
+
|
|
+ rc = uefi_call_wrapper(pciio->Pci.Read, 5, pciio, EfiPciIoWidthUint32,
|
|
+ EFI_FIELD_OFFSET(lpcif_t, rcba), 1, &lpcif.rcba);
|
|
+ if (EFI_ERROR(rc))
|
|
+ return rc;
|
|
+ if (!(lpcif.rcba & 1)) {
|
|
+ Print(L"rcrb is not mapped, cannot route port 80h\n");
|
|
+ return EFI_UNSUPPORTED;
|
|
+ }
|
|
+ lpcif.rcba &= ~1UL;
|
|
+
|
|
+ Print(L"rcba: 0x%8x\n", lpcif.rcba, lpcif.rcba);
|
|
+ set_bit((uint32_t *)(lpcif.rcba + GCS_OFFSET_ADDR),
|
|
+ GCS_RPR_SHIFT, GCS_RPR_PCI);
|
|
+
|
|
+ return EFI_SUCCESS;
|
|
+}
|
|
--
|
|
1.7.1.1
|
|
|