browsing the initrd
Posted: Sat May 28, 2011 3:12 pm
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()
Relevant functions from file.h
media.h
And my test code:
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.
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;
};
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);
};
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
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);
Sorry for calling the initrd initrd.txt, but .img culd not be uploaded to the forum for some reason.