[LinuxBIOS] confusion about enabling resources

Jon Dufresne jon.dufresne at gmail.com
Mon Dec 4 22:50:38 CET 2006

My ram initialization appears to work, at least enough to get me out
of the romcc section.

I am having quite a bit of difficulty getting the bios to run smoothly
though. I am currently stuck somewhere either in filo or somewhere in
elfboot. I think (once again) this has to do with the way LinuxBIOS
understands the ram, and me not properly giving it the information it

As of right now if I put in code that looks more correct to me, the
BIOS dies earlier than if I put in code that looks less correct. I'm
guess that it is a lucky coincidence the less correct code works
better, but it could be that I don't understand what is happening.

In src/northbridge/intel/i855gm/northbridge.c (This northbridge isn't
in the main tree but is based off of i855pm) I have see the following,

mc_dev = dev->link[0].children;

Which I've deduced will give me the PCI device 0:0.0, which is NOT the
MCH for my northbridge. This is used by the line that says

tomk = ((unsigned long)pci_read_config8(mc_dev, 0x63)) << 15;

this will give tomk a value of 0, since that happens to always be in
that register. Obviously I have more than 0 KiB of ram.

To give what I think is the more correct value I modify it to say

mc_dev = dev->link[0].children->sibling;

This will give it the PCI device 0:0.1, which is the MCH. I then
modify the read so it says

tomk = ((unsigned long)pci_read_config8(mc_dev, 0x43)) << 15;

which is the correct register holding the top of the memory (the shift
just puts it into KiB).

Now without my modifications the BIOS makes it into filo and can do
some stuff before dying. With my modifications it dies within elfboot.
With these statements at the end of the log:

Jumping to boot code at 0x10af40
entry    = 0x0010af40
lb_start = 0x00004000
lb_size  = 0x00014000
adjust   = 0x3ffe8000
buffer   = 0x3ffd8000
     elf_boot_notes = 0x0000eb80
adjusted_boot_notes = 0x3fff6b80

In the unmodified form these log statements look like

Jumping to boot code at 0x10af40
entry    = 0x0010af40
lb_start = 0x00004000
lb_size  = 0x00014000
adjust   = 0xfffe8000
buffer   = 0xfffd8000
     elf_boot_notes = 0x0000ec00
adjusted_boot_notes = 0xffff6c00

I am at a loss for what is going wrong here and would appreciate any
insight that anyone has. Below is the unmodified form of the function.
I commented out the pci_write's because those registers are not
documented in my datasheet, nor is there any mention of low memory.

Thanks for any help!

static void pci_domain_set_resources(device_t dev)
	device_t mc_dev;
        uint32_t pci_tolm;

        pci_tolm = find_pci_tolm(&dev->link[0]);
	mc_dev = dev->link[0].children;
	printk_debug("MC dev vid = %x\n", mc_dev->vendor);
	printk_debug("MC dev did = %x\n", mc_dev->device);
	if (mc_dev) {
		/* Figure out which areas are/should be occupied by RAM.
		 * This is all computed in kilobytes and converted to/from
		 * the memory controller right at the edges.
		 * Having different variables in different units is
		 * too confusing to get right.  Kilobytes are good up to
		 * 4 Terabytes of RAM...
		uint16_t tolm_r, remapbase_r, remaplimit_r;
		unsigned long tomk, tolmk;
		unsigned long remapbasek, remaplimitk;
		int idx;

		/* Get the value of the highest DRB. This tells the end of
		 * the physical memory.  The units are ticks of 64MB
		 * i.e. 1 means 64MB.
		tomk = ((unsigned long)pci_read_config8(mc_dev, 0x63)) << 15;
		/* Compute the top of Low memory */
		tolmk = pci_tolm >> 10;
		if (tolmk >= tomk) {
			/* The PCI hole does not overlap memory
			 * we won't use the remap window.
			tolmk = tomk;
			remapbasek   = 0x3ff << 15;
			remaplimitk  = 0 << 15;
		else {
			/* The PCI memory hole overlaps memory
			 * setup the remap window.
			/* Find the bottom of the remap window
			 * is it above 4G?
			remapbasek = 4*1024*1024;
			if (tomk > remapbasek) {
				remapbasek = tomk;
			/* Find the limit of the remap window */
			remaplimitk = (remapbasek + (4*1024*1024 - tolmk) - (1 << 15));
		/* Write the ram configuration registers,
		 * preserving the reserved bits.
		tolm_r = pci_read_config16(mc_dev, 0xc4);
		tolm_r = ((tolmk >> 17) << 11) | (tolm_r & 0x7ff);
		pci_write_config16(mc_dev, 0xc4, tolm_r);

		remapbase_r = pci_read_config16(mc_dev, 0xc6);
		remapbase_r = (remapbasek >> 16) | (remapbase_r & 0xfc00);
		pci_write_config16(mc_dev, 0xc6, remapbase_r);
		remaplimit_r = pci_read_config16(mc_dev, 0xc8);
		remaplimit_r = (remaplimitk >> 16) | (remaplimit_r & 0xfc00);
		pci_write_config16(mc_dev, 0xc8, remaplimit_r);
		/* Report the memory regions */
		printk_debug("tomk = %d\n", tomk);
		printk_debug("tolmk = %d\n", tolmk);
		printk_debug("remaplimitk = %d\n", remaplimitk);
		printk_debug("remapbasek = %d\n", remapbasek);

		idx = 10;
		ram_resource(dev, idx++, 0, 640);
		ram_resource(dev, idx++, 768, tolmk - 768);
		if (tomk > 4*1024*1024) {
			ram_resource(dev, idx++, 4096*1024, tomk - 4*1024*1024);
		if (remaplimitk >= remapbasek) {
			ram_resource(dev, idx++, remapbasek,
				(remaplimitk + 64*1024) - remapbasek);

More information about the coreboot mailing list