-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
I pasted the source from the file in this e-mail, so you can all tell me I am crazy when I am wrong. This ALL came from a GPLed package. I am also attaching the tgz this came out of. Basically it's the src.rpm output. Also, I did an md5sum on the test.rom and the same rom image from the rpm, and they were an exact match. So using the switch I mentioned when I sent out my correction was able to grab the rom image perfectly. Now the trick is getting the rom writable, and low and behold I find a jarrell_rom_jumper.c file with the linux bios source package for this version of linux bios.
Please let me know if this helps, and thanx in advance.
Joshua McDowell
#define _GNU_SOURCE #include <getopt.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/io.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <stdarg.h> #include "./freebios2/src/include/boot/linuxbios_tables.h"
#define PACKED __attribute__((packed))
#define cli() __asm__ __volatile__ ("cli" : : : "memory") #define sti() __asm__ __volatile__ ("sti" : : : "memory")
typedef uint32_t device_t;
#define FLOPPY_DEVICE 0 #define COM1_DEVICE 2 #define COM2_DEVICE 3 #define CWC_DEVICE 4 #define KBC_DEVICE 5 #define CIR_DEVICE 6 #define GPIO_DEVICE 7 #define FMC_DEVICE 9 #define WATCHDOG_DEVICE 0xa #define XBUS_DEVICE 0xf #define RTC_DEVICE 0x10 #define HMC_DEVICE 0x14
#define DEVICE_MAP (\ (1<<0)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<9)|\ (1<<0xa)|(1<<0xf)|(1<<0x10)|(1<<0x14))
#define PNP_BASE_PORT 0x2e
#define PNP_DEV(PORT, FUNC) (((PORT) << 8) | (FUNC))
#define PNP_IDX_IO0 0x60 #define PNP_IDX_IO1 0x62 #define PNP_IDX_IO2 0x64 #define PNP_IDX_IO3 0x66 #define PNP_IDX_IRQ0 0x70 #define PNP_IDX_IRQ1 0x72 #define PNP_IDX_DRQ0 0x74 #define PNP_IDX_DRQ1 0x75
static void enter_pnp(device_t dev) { unsigned port = dev >> 8; unsigned device = dev & 0xff; /* Enter pnp mode */ /* noop */ /* Set the logical device */ outb(0x07, port); outb(device, port +1); }
static void exit_pnp(device_t dev) { /* noop */ }
/* I enter and exit pnp config mode with every access * so when I read an invalid address and potentially * mess up the state machine, the state machine gets * reset. */ static void pnp_write_config(device_t dev, uint8_t reg, uint8_t value) { unsigned port = dev >> 8; cli(); enter_pnp(dev); outb(reg, port); outb(value, port + 1); exit_pnp(dev); sti(); }
static uint8_t pnp_read_config(device_t dev, uint8_t reg) { unsigned port = dev >> 8; uint8_t result; cli(); enter_pnp(dev); outb(reg, port); result = inb(port +1); exit_pnp(dev); sti(); return result; }
static void pnp_set_enable(device_t dev, int enable) { pnp_write_config(dev, 0x30, enable?0x1:0x0); }
static int pnp_read_enable(device_t dev) { return pnp_read_config(dev, 0x30); }
static uint16_t pnp_read_iobase(device_t dev, unsigned index) { uint16_t iobase; iobase = pnp_read_config(dev, index) << 8; iobase |= pnp_read_config(dev, index + 1); return iobase; }
static uint8_t pnp_read_irq(device_t dev, unsigned index) { return pnp_read_config(dev, index); }
static uint8_t pnp_read_drq(device_t dev, unsigned index) { return pnp_read_config(dev, index); }
static void pnp_print_config(device_t dev, FILE *fp) { unsigned device = dev & 0xff; int i; fprintf(fp, "Resource configuration for device: 0x%02x\n", device); fprintf(fp, "Enabled: 0x%02x\n", pnp_read_enable(dev)); fprintf(fp, "iobase0: 0x%04x iobase1: 0x%04x iobase2: 0x%04x iobase3: 0x%04x\n", pnp_read_iobase(dev, PNP_IDX_IO0), pnp_read_iobase(dev, PNP_IDX_IO1), pnp_read_iobase(dev, PNP_IDX_IO2), pnp_read_iobase(dev, PNP_IDX_IO3)); fprintf(fp, "irq0: %2d irq1: %2d drq: %d\n", pnp_read_irq(dev, PNP_IDX_IRQ0), pnp_read_irq(dev, PNP_IDX_IRQ1), pnp_read_drq(dev, PNP_IDX_DRQ0)); for(i = 0x00; i < 256; i++) { unsigned char byte; byte = pnp_read_config(dev, i); if ((i & 0xf) == 0) { fprintf(fp, "%02x: ", i); } fprintf(fp, "%02x ", byte); if ((i & 0xf) == 0xf) { fprintf(fp, "\n"); } } fprintf(fp, "\n"); }
/* * Functions for accessing PCI configuration space with type 1 accesses */
#define PCI_DEV(BUS, DEV, FN) ( \ (((BUS) & 0xFF) << 16) | \ (((DEV) & 0x1f) << 11) | \ (((FN) & 0x7) << 8))
#define PCI_ID(VENDOR_ID, DEVICE_ID) \ ((((DEVICE_ID) & 0xFFFF) << 16) | ((VENDOR_ID) & 0xFFFF))
#define CONFIG_CMD(dev, where) (0x80000000 | dev | (where & ~3))
static uint8_t pci_read_config8(device_t dev, int where) { outl(CONFIG_CMD(dev,where), 0xCF8); return inb(0xCFC + (where&3)); }
static uint16_t pci_read_config16(device_t dev, int where) { outl(CONFIG_CMD(dev,where), 0xCF8); return inw(0xCFC + (where&2)); }
static uint32_t pci_read_config32(device_t dev, int where) { outl(CONFIG_CMD(dev,where), 0xCF8); return inl(0xCFC); }
static void pci_write_config8(device_t dev, int where, uint8_t value) { outl(CONFIG_CMD(dev,where), 0xCF8); outb(value, 0xCFC + (where&3)); }
static void pci_write_config16(device_t dev, int where, uint16_t value) { outl(CONFIG_CMD(dev,where), 0xCF8); outw(value, 0xCFC + (where&2)); }
static void pci_write_config32(device_t dev, int where, uint32_t value) { outl(CONFIG_CMD(dev,where), 0xCF8); outl(value, 0xCFC); }
#undef CONFIG_CMD
#define PCI_DEV_INVALID (0xffffffffU) static device_t pci_locate_device(unsigned pci_id, device_t dev) { for(; dev <= PCI_DEV(255, 31, 7); dev += PCI_DEV(0,0,1)) { unsigned int id; id = pci_read_config32(dev, 0); if (id == pci_id) { return dev; } } return PCI_DEV_INVALID; }
void udelay(int useconds) { struct timeval tv; tv.tv_sec = 0; tv.tv_usec = useconds; select(0, 0, 0, 0, &tv); }
/* jumper pin 1 -> sio_bios_sel (pin 52) jumper pin 2 -> (xbus_r_a20 to ROM) (ich5r pin r2 LDRQ1_N/GPI41) jumper pin 3 -> pull down resistor */
static void die(char *format, ...) { va_list args; va_start(args, format); vfprintf(stderr, format, args); va_end(args); exit(1); }
#define J_DISCONNECTED 0 #define J_1TO2 1 #define J_2TO3 2
void print_jumper_state(int state, FILE *fp) { if (state == J_DISCONNECTED) { fprintf(fp, "High -- disconnected"); } else if (state == J_1TO2) { fprintf(fp, "Toggling -- 1 to 2"); } else if (state == J_2TO3) { fprintf(fp, "Low -- 2 to 3"); } else { die("Impossible Jumper state\n"); } }
int main(int argc, char*argv[]) { device_t ich5r; device_t nsc87427; uint32_t gpio_base; uint32_t gpio_use_sel2, gp_lvl2; uint32_t gp_lvl2_lo, gp_lvl2_hi; uint16_t xbus_base; uint8_t xbimm, xbbsl; FILE *fp; int expected_jumper_state, jumper_state; int i;
expected_jumper_state = J_2TO3;
if (iopl(3) != 0) { die("iopl failed!\n"); }
/* Find the ich5r */ ich5r = pci_locate_device(PCI_ID(0x8086,0x24d0), 0); if (ich5r == PCI_DEV_INVALID) { fprintf(stderr, "Could not find southbridge\n"); } /* Find the gpio bar/base D31:F0 0x58-0x5b */ gpio_base = pci_read_config32(ich5r, 0x58); gpio_base &= ~1; #if 0 fprintf(stdout, "gpio_base: %08x\n", gpio_base); #endif if (gpio_base == 0) { die("gpio_base is not set!\n"); } /* Ensure the gpio line is properly setup */ gpio_use_sel2 = inl(gpio_base + 0x30); #if 0 fprintf(stdout, "gpio_use_sel2: %08x\n", gpio_use_sel2); #endif if ((gpio_use_sel2 & (1 << (41 - 32 ))) == 0) { die("gpio not configured to read high rom address line\n"); } #if 0 /* Read the rom address line */ gp_lvl2 = inl(gpio_base + 0x38); fprintf(stdout, "gp_lvl2: %08x 41=%d\n", gp_lvl2, (gp_lvl2 & (1 << (41 - 32)))?1:0 ); #endif /* Get the superio device */ nsc87427 = PNP_DEV(PNP_BASE_PORT, XBUS_DEVICE);
/* Get the xbus base address */ xbus_base = pnp_read_iobase(nsc87427, PNP_IDX_IO0); if (xbus_base == 0) { die("xbus_base is not set!\n"); } /* Clear the protections bits... */ for(i = 0; i < 32; i++) { outb(((i & 0xf) << 4) | 0, xbus_base + 0x13 + (i >> 4)); }
/* Copy the current xbus high bit confiugration */ xbimm = pnp_read_config(nsc87427, 0xfe); xbbsl = pnp_read_config(nsc87427, 0xff);
/* Disable toggling */ pnp_write_config(nsc87427, 0xff, xbbsl & 0x7f);
/* Force the bit high */ pnp_write_config(nsc87427, 0xfe, xbimm & 0x7f); /* Read the rom address line */ gp_lvl2_lo = !!(inl(gpio_base + 0x38) & (1 << (41 - 32))); #if 0 fprintf(stdout, "41=%d\n", gp_lvl2_lo); #endif
/* Force the bit low */ pnp_write_config(nsc87427, 0xfe, xbimm | 0x80); /* Read the rom address line */ gp_lvl2_hi = !!(inl(gpio_base + 0x38) & (1 << (41 - 32))); #if 0 fprintf(stdout, "41=%d\n", gp_lvl2_hi); #endif /* Restore the xbus high bit configuration */ pnp_write_config(nsc87427, 0xfe, xbimm); pnp_write_config(nsc87427, 0xff, xbbsl);
/* Record the jumper state */ jumper_state = -1; /* Report the jumper state */ if (gp_lvl2_hi != gp_lvl2_lo) { jumper_state = J_1TO2; /* Because it toggles */ } else if (gp_lvl2_lo == 0) { jumper_state = J_2TO3; /* Because it is stuck low */ } else { jumper_state = J_DISCONNECTED; /* Becuase it is stuck high */ } #if 0 /* Print the device registers */ pnp_print_config(nsc87427, stdout);
/* Get the xbus base address */ xbus_base = pnp_read_iobase(nsc87427, PNP_IDX_IO0); if (xbus_base == 0) { die("xbus_base is not set!\n"); } /* Dump the xbus io mapped registers */ for(i = 0; i <= 0x16; i++) { unsigned value; value = inb(xbus_base + i); fprintf(stdout, "%02x ", value); } fprintf(stdout, "\n");
/* Dump the protection bits... */ for(i = 0; i < 32; i++) { unsigned value; outb(((i & 0xf) << 4) | (1 << 3), xbus_base + 0x13 + (i >> 4)); value = inb(xbus_base + 0x13 + (i >> 4)); fprintf(stdout, "%02x ", value); if (((i+1) & 0xf) == 0) { fprintf(stdout, "\n"); } }
#endif /* Report the jumper state */ fp = stdout; fprintf(fp, "Current jumper state: "); print_jumper_state(jumper_state, fp); fprintf(fp, "\n"); if (expected_jumper_state != jumper_state) { fprintf(fp, "Expected: "); print_jumper_state(expected_jumper_state, fp); fprintf(fp, "\n"); exit(1); } return 0; }