[coreboot] jarrel_rom_jumper.c ( I think I found it.. )
Joshua McDowell
jmcdowell at issisolutions.com
Thu May 21 07:53:20 CEST 2009
-----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;
}
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iEYEARECAAYFAkoU7FAACgkQDiqOyViXQA5yYACdE/rch74IhlrBNR66hCSosMBa
gqQAmwfHHXXdZJwINyXb44gFdQlWdKrF
=EBlB
-----END PGP SIGNATURE-----
-------------- next part --------------
A non-text attachment was scrubbed...
Name: linuxbios-jarrell-1.1.7.6.tgz
Type: application/x-compressed-tar
Size: 1593751 bytes
Desc: not available
URL: <http://www.coreboot.org/pipermail/coreboot/attachments/20090521/f9a87f79/attachment.tgz>
More information about the coreboot
mailing list