summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/src/boot/efi/efi.c2
-rw-r--r--sys/src/boot/efi/fns.h1
-rw-r--r--sys/src/boot/efi/iso.c216
-rw-r--r--sys/src/boot/efi/mkfile25
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.*