2002-08-02 15:17:32

by Richard B. Johnson

[permalink] [raw]
Subject: ioremap_nocache(0xfffe0000, 0x00020000);


The AMD SC-520 board uses a 128k BIOS ROM which is decoded
at 0xfffe0000. Of course the real BIOS starts 1/2 way through
it at 0xffff0000. This gets shadowed to F000:0000 in 'real-mode'
as part of the boot sequence.

I want to re-program that BIOS PROM from a driver in Linux.
I find that ioremap_nocache(0xfffe0000, 0x00020000) seems to
'Work', i.e., returns some non-null cookie. However, I can't
access the BIOS ROM. I am accessing something, but it's something
in low memory, not the PROM that is quite identifiable.

/proc/iomem does not show my allocation and says, in fact, that
it's been 'reserved'. I can't understand such a 'reservation' because
I didn't reserve it and I wrote the BIOS.

fec00000-fec00fff : reserved
fee00000-fee00fff : reserved
ffff0000-ffffffff : reserved


Snippit from module init...


#define PROM_BASE 0xfffe0000
#define PROM_LEN 0x00020000 (also tried 0x0001ffff)



int __init init_module()
{
int result;
if((cp = (UC *) ioremap_nocache(PROM_BASE, PROM_LEN)) == NULL)
{
printk(KERN_ERR"%s : Can't access PROM\n", dev);
return -EACCES;
}

If I do:

if(copy_to_user((UC *)arg, cp, PROM_LEN))
return -EFAULT;

... as an ioctl() with the passed arg, and cp being the cookie from
ioremap_nocache()... This hangs (forever) with no panic(). If I
copy first to a kmalloc() buffer, then to the user, it goes okay,
but it's not the PROM image, it's something within the kernel's
RAM that I'm looking at.

Anybody got any hints? FYI, If I substitute other addresses, I can
access other PROMS including the Adaptec PROM in its controller
via PCI, plus the shadowed one in low RAM. Same with screen-card
BIOS. There seems to be something about the 0xfffe0000 address that
the kernel doesn't like. Also, from user-mode, I can't mmap any
addresses above about 0xbfffffff. This may be part of the same problem.

Anybody have any idea?


Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
The US military has given us many words, FUBAR, SNAFU, now ENRON.
Yes, top management were graduates of West Point and Annapolis.


2002-08-05 13:09:53

by Jon Burgess

[permalink] [raw]
Subject: Re: ioremap_nocache(0xfffe0000, 0x00020000);



I used the program below to get a copy of Bios rom on a National Geode / CS5530
board. If I remember correctly this code depended on the chipset decoding the
rom at this specific address range, the 'standard' address range was
0xC0000..0xFFFFF but not all the Rom was available here. If you wanted to write
to the rom then it needed some other chipset bits set correctly as well.

You could also take a look at the
linux-2.4.19/drivers/mtd/maps/{netsc520.c,sc520cdp.c}.

You could probably acomplish the same with the right 'dd if=/dev/mem of=bios.rom
...'

Jon Burgess

/* dumprom.c
*
* Dump BIOS Rom space to a file
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>

// To read the full 4Mbit ROM it needs to be accessed at the 'high' address
range
// Only 128Kb is available at 'low' address of 0xc0000
#define START 0xfff80000
#define LENGTH 0x00080000

int main(int argc, char *argv[])
{
void *pmem;
int fd, fd2;

if (argc != 2)
{
printf("%s: <filename>\n", argv[0]);
printf("Writes the BIOS memory space out to the file specifed\n");
exit(1);
}

fd2 = open(argv[1], O_WRONLY | O_CREAT);
if (!fd2)
{
perror("Error creating file");
exit(1);
}

/* Get access BIOS memory space */
fd = open("/dev/mem", O_RDONLY);
if(!fd)
{
perror("Error opening /dev/mem");
close(fd2);
exit(1);
}

pmem = mmap(0, LENGTH, PROT_READ, MAP_SHARED, fd, START);
if (pmem == MAP_FAILED)
{
perror("Error mapping /dev/mem");
close(fd2);
close(fd);
exit(1);
}

if (write(fd2, pmem, LENGTH) == -1)
{
perror("Error writing data");
close(fd2);
close(fd);
exit(2);
}

munmap(pmem, LENGTH);

close(fd);
close(fd2);

exit(0);
}