Page 1 of 1

browsing the initrd

Posted: Sat May 28, 2011 3:12 pm
by mariuszp
I use GRUB to load an initrd as a multiboot module. Everything works fine, until I try to read a file from the initrd. The problem is that the initrd_next() function which is used to browse files does not "see" the file hello.txt, and gets stuck on '/', which is crap. So the search_file() function seems to fall into an infinite loop. Here's some code:

initrd_next()

Code: Select all

bool initrd_next(dirent_t *dirent)
{
	initrd_head_t header;
	media_acquire(dirent->d_resv[INITRD_MEDIA]);
	media_begin(dirent->d_resv[INITRD_MEDIA]);
	media_read(dirent->d_resv[INITRD_MEDIA], 0, 1, &header);

	initrd_record_t *records;
	records = (initrd_record_t*) kmalloc(512*header.nblkat);
	if (!records)
	{
		media_release(dirent->d_resv[INITRD_MEDIA]);
		return false;
	};
	media_read(dirent->d_resv[INITRD_MEDIA], 1, header.nblkat, records);
	media_end(dirent->d_resv[INITRD_MEDIA]);
	media_release(dirent->d_resv[INITRD_MEDIA]);

	/* check to see if there IS a next record */
	printk("initrd_next: "); printk(dirent->d_name); printk(" next="); printk(records[dirent->d_fileno+1].filename);
	printk("fileno_current="); printdec(dirent->d_fileno); printk("\n");
	if (records[dirent->d_fileno+1].filename[0] != 0)
	{
		int fno = dirent->d_fileno+1;
		dirent->d_fileno = fno;
		strcpy(dirent->d_name, records[fno].filename);
		printk("initrd_next: "); printk(dirent->d_name); printk(" fileno="); printdec(dirent->d_fileno); printk("\n");
		dirent->d_type = records[fno].type;
		kfree(records);
		return true;
	};

	return false;
};
Relevant functions from file.h

Code: Select all

bool search_file(dirent_t *dirent, filesystem_t *fs, char * filename)
{
	if (filename[0] == '/') return true;
	printk("search_file: "); printk(filename); printk("\n");
	while (strcmp(dirent->d_name, filename) != 0)
	{
		printk("dirent->d_name: "); printk(dirent->d_name); printk("\n");
		if (!fs->nodi_next(dirent))
		{
			fs->nodi_add(dirent, filename, DT_REG);
		};
	};
	return true;
};

bool *find_node(dirent_t *dirent, pathname_t *pathname)
{
	if (!pathname) return false;
	while (pathname != NULL)
	{
		if (!search_file(dirent, rootfs, pathname->name)) return false;
		if (pathname->next != NULL)
		{
			if (!rootfs->nodi_down(dirent)) return false;
		};
		pathname = pathname->next;
	};
	return true;
};

iohandle_t *open(const char * filename)
{
	pathname_t *pathname = (pathname_t*) kmalloc(sizeof(pathname_t));
	int t;
	t = pathname_split(filename, pathname);
	if (t == FP_BAD) return NULL;
	if (t == FP_RELATIVE)
	{
		u32int temp = (u32int) pathname;
		pathname = pathname_absolute(pathname);
		kfree(temp);
	};
	dirent_t *dirent;
	dirent = (dirent_t*) kmalloc(sizeof(dirent_t));
	memcpy(dirent, rootdirent, sizeof(dirent_t));
	if(!find_node(dirent, pathname)) return NULL;
	return rootfs->nodi_getio(dirent);
};
media.h

Code: Select all

/* the following driver functions should update the flags field upon result */
typedef void (*media_read_t)(struct media_struct*, u32int, u32int, char*);
typedef void (*media_write_t)(struct media_struct*, u32int, u32int, char*);
typedef void (*media_begin_t)(struct media_struct*);
typedef void (*media_end_t)(struct media_struct*);

typedef struct media_struct
{
	char		label[128];		/* 'label' (or 'name') of the media. */
	u32int		size;			/* size (in blocks!) of the media. */
	u32int		flags;			/* any extra flags */
	bool		lock;			/* is the lock active? */
	u32int		id;			/* recognised by DRIVER, not the whole kernel */
	media_read_t	mread;
	media_write_t	mwrite;
	media_begin_t	mbegin;
	media_end_t	mend;
} __attribute__ ((packed)) media_t;

bool media_poll(media_t *media)
{
	return !media->lock;
};

void media_acquire(media_t *media)
{
	while (!media_poll(media));
	media->lock = true;
};

void media_release(media_t *media)
{
	media->lock = false;
};

void media_begin(media_t *media)
{
	media->mbegin(media);
};

void media_end(media_t *media)
{
	media->mend(media);
};

void media_read(media_t *media, u32int sector, u32int count, char * buffer)
{
	media->mread(media, sector, count, buffer);
};

void media_write(media_t *media, u32int sector, u32int count, char * buffer)
{
	media->mwrite(media, sector, count, buffer);
};

#endif
And my test code:

Code: Select all

	debug("Initialising initrd filesystem...\n");
	rootfs = &fs_initrd;
	initrd_media = create_ramdisk(begin, end, "initrd");
	if(!initrd_media) halt("failed to create ramdisk");
	rootdirent = rootfs->init(initrd_media, 1, -1);
	if (!rootdirent) halt("initrdfs reports error!");

	printk("hi.\n");
	iohandle_t *fp = open("/hello.txt");
	printk("hi again.\n");
	if (!fp) halt("failed.");
	char buffer[1024];
	read(buffer, 1, 5, fp);
	close(fp);
If you want me to upload my initrd creator code, I can do that too.

Sorry for calling the initrd initrd.txt, but .img culd not be uploaded to the forum for some reason.

Re: browsing the initrd

Posted: Sun May 29, 2011 11:42 am
by mariuszp
anyone?

Re: browsing the initrd

Posted: Sun May 29, 2011 12:10 pm
by Combuster
Since you asked: too much code, too few comments, code in .h files, problem description insufficient. You have a ton of print* statements and yet we're being withheld from the information that supposedly appears on your screen.

In other words: program smart, ask smart.

Re: browsing the initrd

Posted: Sun May 29, 2011 12:18 pm
by mariuszp
Here's what appears in my screen:

Code: Select all

dirent->d_name: /
initrd_next: / next=fileno_current=0
The whole problem is hard to explain. It appears that records[1].filename[0] is 0, butif you look into the initrd file, you can notice that it isn't (try GHex). The first 512 bytes of the initrd are the header, and straight after that there are two files. The first one does not matter (it's just padding because index 0 should be '/' but the initrd doesn't care), and if you notice, straight after that there is the next record structure, which begins with the filename field, which says 'hello.txt'. I don't know what's going on.

Re: browsing the initrd

Posted: Sun May 29, 2011 1:33 pm
by Combuster
It appears that records[1].filename[0] is 0
Go on, how did that get there? Addresses, watchpoints, bochs, hint?