Click to See Complete Forum and Search --> : Extract BIOS info


snrem
03-29-2001, 12:08 AM
HI,
Please help. I need to extract the BIOS information like the BIOS ID, mother board manufacturer and etc from the BIOS from Linux. Does anyone know how to get such information besides lookig at the POST message?
In Windows, I can use int calls to read the SM BIOS or even use debug. But how do I do it on Linux.

thanks
rem :confused:

Ben Briggs
03-29-2001, 12:14 AM
I could be wrong... but I'm pretty sure you can't from Linux. The reason is because Linux runs in protected mode (as opposed to Windows runs in real mode). If I am wrong... someone will correct me :). That's what so great about LNO! Somebody knows the answer to pretty much every question!

augur
03-29-2001, 07:13 AM
Well, actualy Windows runs in protected mode too. In windows DOS program can use interrupts and peek at memory below 1MB because they are run in a real mode emulation, called virtual mode 86. But it is still protected mode.
Not sure if you could achieve the same results with DOS emu in linux.
You will not be able to call interrupts in linux, except for int 0x80, which is how system calls are implemented in linux. You could map the BIOS memory area into your program's working area and access it this way, I think, I'm new to linux programming myself.
Anyway, check http://linuxassembly.org/modex.html for an example on how access the VGA registers and access video memory directly.
Hope this helps.

pinoy
03-30-2001, 08:21 AM
You can read /dev/kmem. It is your phyiscal memory. Also if you need to read/write to the cmos, you can also compile in nvram support and read /dev/nvram.

snrem
04-02-2001, 05:03 AM
Thanks for the information but I'm new to Linux kernel and there isn't much reading on kmem.

Appreciate if you could point me to some useful readings on kmem and especially on accessing memory below 1MB in Linux.

Thanks
snrem

pinoy
04-03-2001, 07:00 AM
Well it's either /dev/kmem or /dev/mem. I think it's actually /dev/mem that represents your physical memory.

What you need to do is open /dev/mem using open(2), then seek to the correct location of memory you want to read.

Here's some sample code I wrote quickly to dump physical memory.


--dumpmem.c--
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

#ifndef min
#define min(a,b) ((a) < (b)) ? (a) : (b)
#endif

void dumpBytes(const char *buf, int len);
void dumpAscii(const char *buf, int len);

int main(int argc, char *argv[])
{
int offset, bytes;
int memfd;
char buf[1024];

if (argc < 3) {
printf("dumpmem <start> <bytes> [/dev/mem]\n");
return 0;
}

offset = atoi(argv[1]);
bytes = atoi(argv[2]);

if (argc > 3)
memfd = open(argv[3], O_RDONLY);
else
memfd = open("/dev/mem", O_RDONLY);

if (memfd == -1) {
perror("cannot open /dev/mem\n");
return 0;
}

lseek(memfd, offset, SEEK_SET);
while (bytes > 0) {
int bytesToRead = min(bytes, sizeof(buf));
ssize_t bytesRead = read(memfd, buf, bytesToRead);
bytes -= bytesRead;
if (bytesRead <= 0)
break;

dumpBytes(buf, bytesRead);
}
}

void dumpBytes(const char *buf, int len)
{
char hexTable[] = "0123456789abcdef";
const char *ptr = buf;
const char *ptrStartOfLine = ptr;
int bytesWrittenPerLine = 0;

while (len--) {
fputc(hexTable[ (*ptr >> 4) & 0x0f ], stdout);
fputc(hexTable[ *ptr & 0x0f ], stdout );
fputc(' ', stdout);
bytesWrittenPerLine++;

if (bytesWrittenPerLine == 8) {
fputc('-', stdout);
fputc(' ', stdout);
}
if (bytesWrittenPerLine == 16) {
dumpAscii(ptrStartOfLine, 16);
bytesWrittenPerLine = 0;
ptrStartOfLine = ptr;
}

ptr++;
}

if (bytesWrittenPerLine) {
/* pad out to 16 bytes */
int bytes = bytesWrittenPerLine;
while (bytesWrittenPerLine++ < 16) {
fputc(' ', stdout); fputc(' ', stdout); fputc(' ', stdout);
if (bytesWrittenPerLine == 8)
fputc('-', stdout), fputc(' ', stdout);
}
dumpAscii(ptrStartOfLine, bytes);
}
}

void dumpAscii(const char *buf, int len)
{
const char *end = buf + len;
while (buf < end) {
if (isprint((unsigned)*buf))
fputc(*buf, stdout);
else
fputc('.', stdout);
buf++;
}
fputc('\n', stdout);
}

# cc -o dumpmem dumpmem.c
to compile.

To dump 1024 bytes of the kernel's memory starting at 10 (you have to be root to run this).

# ./dumpmem 10 1024 /dev/kmem

pinoy
04-03-2001, 07:46 AM
BTW: You need to consult an old x86 assembler book to tell you where you find BIOS information in memory.

eg. One of my old books say that the serial number and copyright info is stored in 0xfe000 (1040384 decimal).

# ./dumpmem 1040384 256

pinoy
04-07-2001, 09:45 PM
okay, in the spirit of JemFinch's enthusiasm about Python, I've decided to write the above code in Python, and see exactly how much shorter it would be.

Yes I agree Python is easy to learn and fun (it only took me a few minutes to do the script below after looking at the various tutorials). But the code below is not much shorter than my C code, and in fact I'm sure I can still shorten my C code, if I wanted to (and also it only took me a few minutes to write the above code, it took me a lot longer to get proficient in C though).

I'm sure there must a better way of doing this, so anyone care to show me how.


#!/usr/bin/python

import sys
import string

def isPrint(ch):
# print anything that is seven bits, and greater than ' '?
if ch in range( ord(" "), 127 ):
return 1
return 0

def toInt(data):
retval = []
line = []
for b in data:
line.append( ord(b) )
if len(line) == 16:
retval.append(line)
line = []

if len(line) > 0:
retval.append(line)

return retval

def dumpHex(data, output=sys.stdout):
intvals = toInt(data)
for line in intvals:
bytes = 0
for byte in line:
output.write("%02x " % byte)
bytes = bytes + 1
if bytes == 8:
output.write("- ")
while bytes < 16:
output.write(" ")
bytes = bytes + 1
if bytes == 8:
output.write("- ")

for byte in line:
if isPrint(byte):
output.write("%s" % chr(byte))
else:
output.write(".")

output.write("\n")

def dumpFile(filename, offset, len):
f = open(filename, "rb")
if not f:
print "cannot open %s" % filename
return 0

f.seek(offset)
buf = f.read(len)
dumpHex(buf)

if __name__ == "__main__":
if len(sys.argv) < 3:
print "dumpmem.py <start> <offset> [/dev/kmem]"
sys.exit(0)

try:
offset = string.atoi(sys.argv[1])
bytes = string.atoi(sys.argv[2])
except (string.atoi_error):
print "invalid arguments"
sys.exit(0)

filename = "/dev/mem"
if len(sys.argv) > 3:
filename = sys.argv[3]

dumpFile(filename, offset, bytes)

Qubit
04-08-2001, 03:33 AM
Hehe, this comes from arch/i386/boot/setup.S

! we don't need no steenking BIOS anyway (except for the initial loading :-)

I found that by accident, it reflects pretty good the attitude :)

pinoy
04-09-2001, 06:41 AM
Yep. Most 32bit systems don't use the BIOS at all. The Linux kernel actually overwrites the memory occupied by the BIOS, on boot up. Alessandro Rubini wrote an article about this in one of the old issues of Linux Journal (can't remember which one, about 2-3 years ago). Anyway, I don't know how much of it is overwritten as clearly some of the data is still there. The BIOS don't really have much use under Linux. If you want to read disk sectors, just read the appropriate device rather than using the BIOS.

Anyway on another topic, I've been playing further with Python. I'm a little bit happier with it now. I wrote a Python implementation of the RC4 stream cipher, and this time at least it's half as many lines as the C reference. Unfortunately I've seen people write this in 3 lines of Perl!.


#!/usr/bin/python

import sys

class RC4:
def __init__(self):
self.state = []
self.x = 0
self.y = 0

def resetState(self):
del self.state
self.state = []
self.x = 0
self.y = 0
for i in range(0, 256):
self.state.append(i)

def prepareKey(self, key):
self.resetState()
index1 = 0
index2 = 0
for i in range(0, 256):
index2 = (ord(key[index1]) + self.state[i] + index2) % 256
(self.state[i], self.state[index2]) = (self.state[index2], self.state[i])
index1 = (index1 + 1) % len(key)


def encrypt(self, data):
x = self.x
y = self.y
ret = ""
for i in range(0, len(data)):
x = (x + 1) % 256
y = (self.state[x] + y) % 256
(self.state[x], self.state[y]) = (self.state[y], self.state[x])
xorIndex = (self.state[x] + self.state[y]) % 256
c = ord(data[i])
ret = ret + chr(c ^ self.state[xorIndex])

self.x = x
self.y = y
return ret

def main():
if len(sys.argv) < 2:
sys.stderr.write("rc4 key < input > output\n");
sys.exit(0)

rc4 = RC4()
rc4.prepareKey(sys.argv[1])
sys.stdout.write(rc4.encrypt(sys.stdin.read()))

if __name__ == "__main__":
main()


Python Gurus: how the hell do I deal with binary data as strings efficiently. e.g. in the above code, I do some arithmetic calculations on every byte/character of the string (xor, and additions). How do I do this without having to convert it with ord(), then back to chr() again?