diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-10-31 19:43:47 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-10-31 19:43:47 +0100 |
commit | c7a5345aa6af80bd569e21b576c16daf3a0c72ea (patch) | |
tree | 255fc2cf5f8fdbd25cfbf4d26a55de582d0d8a0e /sys/src/boot | |
parent | 5f91d3f484db5354eba22dd94162e45a708e369a (diff) |
efi: iso filesystem support for cdrom booting
instead of including kernel and config in the efi
fat image, we can just include the loaders and
read the plan9.ini and kernel from iso filesystem
just like the bios loaders.
Diffstat (limited to 'sys/src/boot')
-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.* |