diff options
| -rw-r--r-- | sys/src/boot/efi/efi.c | 2 | ||||
| -rw-r--r-- | sys/src/boot/efi/fns.h | 1 | ||||
| -rw-r--r-- | sys/src/boot/efi/iso.c | 216 | ||||
| -rw-r--r-- | sys/src/boot/efi/mkfile | 25 |
4 files changed, 237 insertions, 7 deletions
diff --git a/sys/src/boot/efi/efi.c b/sys/src/boot/efi/efi.c index ae9055c92..3102aac50 100644 --- a/sys/src/boot/efi/efi.c +++ b/sys/src/boot/efi/efi.c @@ -291,7 +291,7 @@ efimain(EFI_HANDLE ih, EFI_SYSTEM_TABLE *st) ST = st; f = nil; - if(pxeinit(&f) && fsinit(&f)) + if(pxeinit(&f) && isoinit(&f) && fsinit(&f)) print("no boot devices\n"); for(;;){ diff --git a/sys/src/boot/efi/fns.h b/sys/src/boot/efi/fns.h index 58dbe32e6..e029ebdb6 100644 --- a/sys/src/boot/efi/fns.h +++ b/sys/src/boot/efi/fns.h @@ -8,6 +8,7 @@ void usleep(int t); void jump(void *pc); int pxeinit(void **pf); +int isoinit(void **pf); int fsinit(void **pf); void* (*open)(char *name); diff --git a/sys/src/boot/efi/iso.c b/sys/src/boot/efi/iso.c new file mode 100644 index 000000000..b11e19d2e --- /dev/null +++ b/sys/src/boot/efi/iso.c @@ -0,0 +1,216 @@ +#include <u.h> +#include "fns.h" +#include "efi.h" + +enum { + Sectsz = 0x800, + Dirsz = 33, +}; + +typedef struct Extend Extend; +typedef struct Dir Dir; + +struct Extend +{ + 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; +}; + +typedef struct { + UINT32 MediaId; + + BOOLEAN RemovableMedia; + BOOLEAN MediaPresent; + BOOLEAN LogicalPartition; + BOOLEAN ReadOnly; + + BOOLEAN WriteCaching; + BOOLEAN Pad[3]; + + UINT32 BlockSize; + UINT32 IoAlign; + UINT64 LastBlock; +} EFI_BLOCK_IO_MEDIA; + +typedef struct { + UINT64 Revision; + EFI_BLOCK_IO_MEDIA *Media; + void *Reset; + void *ReadBlocks; + void *WriteBlocks; + void *FlushBlocks; +} EFI_BLOCK_IO_PROTOCOL; + +static EFI_GUID +EFI_BLOCK_IO_PROTOCO_GUID = { + 0x964e5b21, 0x6459, 0x11d2, + 0x8e, 0x39, 0x00, 0xa0, + 0xc9, 0x69, 0x72, 0x3b, +}; + +static EFI_BLOCK_IO_PROTOCOL *bio; + +static int +readsect(ulong lba, void *buf) +{ + return eficall(bio->ReadBlocks, bio, (UINTN)bio->Media->MediaId, (UINT64)lba, (UINTN)Sectsz, buf); +} + +static int +isoread(void *f, void *data, int len) +{ + Extend *ex = f; + + if(ex->len > 0 && ex->rp >= ex->ep) + if(readsect(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 +isoclose(void *f) +{ + Extend *ex = f; + + ex->lba = 0; + ex->len = 0; + ex->rp = ex->ep = ex->buf + Sectsz; +} + +static int +isowalk(Extend *ex, char *path) +{ + char name[MAXPATH], c, *end; + int i; + Dir d; + + isoclose(ex); + + /* find pvd */ + for(i=0x10; i<0x1000; i++){ + if(readsect(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; + } + } + return -1; +} + +static void* +isoopen(char *path) +{ + static Extend ex[1]; + + if(isowalk(ex, path)) + return nil; + return ex; +} + +int +isoinit(void **fp) +{ + EFI_BLOCK_IO_MEDIA *media; + EFI_HANDLE *Handles; + UINTN Count; + int i; + + bio = nil; + Count = 0; + Handles = nil; + if(eficall(ST->BootServices->LocateHandleBuffer, + ByProtocol, &EFI_BLOCK_IO_PROTOCO_GUID, nil, &Count, &Handles)) + return -1; + + for(i=0; i<Count; i++){ + bio = nil; + if(eficall(ST->BootServices->HandleProtocol, + Handles[i], &EFI_BLOCK_IO_PROTOCO_GUID, &bio)) + continue; + + media = bio->Media; + if(media != nil + && media->MediaPresent + && media->RemovableMedia + && media->LogicalPartition == 0 + && media->BlockSize == Sectsz) + goto Found; + } + return -1; + +Found: + open = isoopen; + read = isoread; + close = isoclose; + + if(fp != nil) + *fp = isoopen("/cfg/plan9.ini"); + + return 0; +} diff --git a/sys/src/boot/efi/mkfile b/sys/src/boot/efi/mkfile index c655dc430..2dddd1e4e 100644 --- a/sys/src/boot/efi/mkfile +++ b/sys/src/boot/efi/mkfile @@ -10,7 +10,7 @@ install:V: $TARG cp bootia32.efi /386 cp bootx64.efi /386 -bootia32.efi: pe32.8 efi.8 fs.8 pxe.8 sub.8 +bootia32.efi: pe32.8 efi.8 fs.8 pxe.8 iso.8 sub.8 8l -l -H3 -T$IMAGEBASE -o $target $prereq pe32.8: pe32.s @@ -25,13 +25,16 @@ fs.8: fs.c efi.h pxe.8: pxe.c efi.h 8c $CFLAGS pxe.c +iso.8: iso.c efi.h + 8c $CFLAGS iso.c + sub.8: sub.c 8c $CFLAGS sub.c %.8: $HFILES -bootx64.efi: pe64.6 efi.6 fs.6 pxe.6 sub.6 +bootx64.efi: pe64.6 efi.6 fs.6 pxe.6 iso.6 sub.6 6l -l -s -R1 -T$IMAGEBASE -o bootx64.out $prereq dd -if bootx64.out -bs 1 -iseek 40 >$target @@ -47,6 +50,9 @@ fs.6: fs.c efi.h pxe.6: pxe.c efi.h 6c $CFLAGS pxe.c +iso.6: iso.c efi.h + 6c $CFLAGS iso.c + sub.6: sub.c 6c $CFLAGS sub.c @@ -55,8 +61,8 @@ sub.6: sub.c test.fat:D: bootia32.efi bootx64.efi s = $target.$pid - rm -f /srv/$s $target - dd -if /dev/zero -of $target -bs 65536 -count 256 + rm -f $target + dd -if /dev/zero -of $target -bs 65536 -count 128 disk/format -xd -t hard $target dossrv -f $target $s mount -c /srv/$s /n/esp @@ -70,8 +76,15 @@ test.fat:D: bootia32.efi bootx64.efi rm /srv/$s test.iso:D: test.fat - disk/mk9660 -E test.fat -p <{echo test.fat} -s . $target - + rm -fr tmp + mkdir tmp + cp test.fat tmp + mkdir tmp/cfg + mkdir tmp/386 + cp /386/9pcf tmp/386 + echo 'bootfile=/386/9pcf' >tmp/cfg/plan9.ini + disk/mk9660 -E test.fat -p <{echo +} -s tmp $target + rm -r tmp clean:V: rm -f *.[68] *.out $TARG test.* |
