[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