browsing the initrd

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
mariuszp
Member
Member
Posts: 587
Joined: Sat Oct 16, 2010 3:38 pm

browsing the initrd

Post 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.
mariuszp
Member
Member
Posts: 587
Joined: Sat Oct 16, 2010 3:38 pm

Re: browsing the initrd

Post by mariuszp »

anyone?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: browsing the initrd

Post 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.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
mariuszp
Member
Member
Posts: 587
Joined: Sat Oct 16, 2010 3:38 pm

Re: browsing the initrd

Post 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.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: browsing the initrd

Post by Combuster »

It appears that records[1].filename[0] is 0
Go on, how did that get there? Addresses, watchpoints, bochs, hint?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Post Reply