Page 1 of 1

extremely weird error

Posted: Thu May 26, 2011 2:13 pm
by mariuszp
OK, first, let me show you some code...

initrd_init() function:

Code: Select all

	(void)part;
	initrd_head_t header;
	media_acquire(media);
	media_begin(media);
	media_read(media, 0, 1, &header);
	printhex(media); printk("\n");
	while(1);
	media_end(media);
	media_release(media);
media_read():

Code: Select all

void media_read(media_t *media, u32int sector, u32int count, char * buffer)
{
	printhex(media); printk("\n");
	media->mread(media, sector, count, buffer);
	printhex(media); printk("\n");
};
media->mread is actually ramdisk_read():

Code: Select all

void ramdisk_read(media_t * media, u32int sector, u32int count, char * buffer)
{
	if ((sector+count)*512 > media->size) count = (media->size-sector);
	char * intbuf = (char *) (media->id + 512 * sector);
	memcpy(buffer, intbuf, count*512);
	printhex(media); printk("\n");
};
As you can see, all these functions keep on printing the media pointer, and in all cases, that pointer is 0x003002E0. The last printhex(), done by media_read() presents the correct pointer, but as soon as this function returns, the pointer printed by initrd_init() is 0, and that causes page faults! Does anyone see why this value is suddenly updated when media_read() returns?

Re: extremely weird error

Posted: Thu May 26, 2011 3:34 pm
by bluemoon
Try this:

Code: Select all

void ramdisk_read(media_t * media, u32int sector, u32int count, char * buffer)
{
   if ((sector+count)*512 > media->size) count = (media->size-sector);
   char * intbuf = (char *) (media->id + 512 * sector);

   printhex(buffer); printk("<--buffer\n");
   printhex(intbuf); printk("<--inbuf\n");   // intbuf or inbuf?
   printhex(count); printk("<--count\n");

   memcpy(buffer, intbuf, count*512);  // this may overrun a lot of things
   printhex(media); printk("<--media\n");  // media is local variable on the stack so it may survive.
};
and also add to your init function:

Code: Select all

printhex(&head); printk("<--&head\n");
First suspect is buffer, as it's the only place have write access to memory, and it's writing bytes into what pointed by &head, and perhaps overrun anything after it.
If buffer < &media < buffer+count, ie. they overlaps, then it should be the cause.

Re: extremely weird error

Posted: Fri May 27, 2011 12:25 pm
by mariuszp
I mean intbuf (Internal Buffer). media->id is just above the 1MB mark, it is where my initrd is loaded by GRUB. And the buffer is on the stack, so I don't see how it could be after the media->id + (count*512). And the intbuf is 3K, and the count is one, so I only read up to 0.5K.

Perhaps I should just check my memcpy() function? By the way, one more thing:

Code: Select all

	u32int mtemp = (u32int) media;
	initrd_head_t header;
	media_acquire(media);
	media_begin(media);
	media_read(media, 0, 1, &header);
	media = (media_t*) mtemp;
When I do THAT, the final pointer is 0x74696E69, which seems sort-of weird..

P.S. here's my memcpy() function:

Code: Select all

void memcpy(char *tar, char *src, int count)
{
	while (count--)
	{
		*tar++ = *src++;
	};
};

Re: extremely weird error

Posted: Fri May 27, 2011 12:39 pm
by mariuszp
Oops, I figured out what was wrong:

Code: Select all

	//if ((sector+count)*512 > media->size) count = ((media->size/512)-sector);
After I comment this out, everything works. Anyone knows what's wrong with this line? It's bound-checking. media->size is the size of the media in blocks (1 block = 512 bytes).

Re: extremely weird error

Posted: Sat May 28, 2011 3:52 am
by bluemoon

Code: Select all

//if ((sector+count)*512 > media->size) count = ((media->size/512)-sector);
There is potential issue if sector > media->size, you will get billion counts.

To the original problem, what's the structure of initrd_head_t? Do it have enough space to store the read() ?
The symtom suggest you have overwritten things on stack of initrd_init(), which hold the "media_t *media" local variable with wrong content.