plan9front/sys/src/boot/pc/iso.c

197 lines
3.0 KiB
C

#include <u.h>
#include "fns.h"
enum {
Sectsz = 0x800,
Maxpath = 256,
Dirsz = 33,
};
typedef struct Extend Extend;
typedef struct Dir Dir;
struct Extend
{
int drive;
ulong lba;
ulong len;
uchar *rp;
uchar *ep;
uchar buf[Sectsz];
};
struct Dir
{
uchar dirlen;
uchar extlen;
uchar lba[8];
uchar len[8];
uchar date[7];
uchar flags[3];
uchar seq[4];
uchar namelen;
};
int readsect(ulong drive, ulong lba, void *buf);
#ifdef FAT
int
readsect4(ulong drive, ulong lba, void *buf)
{
int i;
lba *= Sectsz/512;
for(i = 0; i<Sectsz/512; i++){
if(readsect(drive, lba++, buf))
return -1;
buf = (uchar*)buf + 512;
}
return 0;
}
#define readsect readsect4
#endif
void
unload(void)
{
}
int
read(void *f, void *data, int len)
{
Extend *ex = f;
if(ex->len > 0 && ex->rp >= ex->ep)
if(readsect(ex->drive, ex->lba++, ex->rp = ex->buf))
return -1;
if(ex->len < len)
len = ex->len;
if(len > (ex->ep - ex->rp))
len = ex->ep - ex->rp;
memmove(data, ex->rp, len);
ex->rp += len;
ex->len -= len;
return len;
}
void
close(void *f)
{
Extend *ex = f;
ex->drive = 0;
ex->lba = 0;
ex->len = 0;
ex->rp = ex->ep = ex->buf + Sectsz;
}
static int
isowalk(Extend *ex, int drive, char *path)
{
char name[Maxpath], c, *end;
int i;
Dir d;
close(ex);
ex->drive = drive;
/* find pvd */
for(i=0x10; i<0x1000; i++){
if(readsect(drive, i, ex->buf))
return -1;
if(*ex->buf == 1)
break;
}
ex->lba = *((ulong*)(ex->buf + 156 + 2));
ex->len = *((ulong*)(ex->buf + 156 + 10));
for(;;){
if(readn(ex, &d, Dirsz) != Dirsz)
break;
if(d.dirlen == 0)
break;
if(readn(ex, name, d.namelen) != d.namelen)
break;
i = d.dirlen - (Dirsz + d.namelen);
while(i-- > 0)
read(ex, &c, 1);
for(i=0; i<d.namelen; i++){
c = name[i];
if(c >= 'A' && c <= 'Z'){
c -= 'A';
c += 'a';
}
name[i] = c;
}
name[i] = 0;
while(*path == '/')
path++;
if((end = strchr(path, '/')) == 0)
end = path + strlen(path);
i = end - path;
if(d.namelen == i && memcmp(name, path, i) == 0){
ex->rp = ex->ep;
ex->lba = *((ulong*)d.lba);
ex->len = *((ulong*)d.len);
if(*end == 0)
return 0;
else if(d.flags[0] & 2){
path = end;
continue;
}
break;
}
}
close(ex);
return -1;
}
void
start(void *sp)
{
char path[Maxpath], *kern;
int drive;
Extend ex;
void *f;
/* drive passed in DL */
drive = ((ushort*)sp)[5] & 0xFF;
#ifndef FAT
/*
* load full bootblock as only the frist 2K get
* loaded from bios. the code is specially arranged
* to have all the important routines in the first
* 2K of the 9bootiso image. (strings have been
* placed in l.s to make sure they will be < 2K)
*/
if(isowalk(&ex, drive, bootname)){
print(bootname);
putc('?');
halt();
}
readn(&ex, origin, ex.len);
close(&ex);
#endif
if(isowalk(f = &ex, drive, "/cfg/plan9.ini")){
print("no config\n");
f = 0;
}
for(;;){
kern = configure(f, path); f = 0;
if(isowalk(&ex, drive, kern)){
print("not found\n");
continue;
}
print(bootkern(&ex));
print("\n");
}
}