ref: c7a5345aa6af80bd569e21b576c16daf3a0c72ea
parent: 5f91d3f484db5354eba22dd94162e45a708e369a
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Oct 31 15:43:47 EDT 2014
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.
--- a/sys/src/boot/efi/efi.c
+++ b/sys/src/boot/efi/efi.c
@@ -291,7 +291,7 @@
ST = st;
f = nil;
- if(pxeinit(&f) && fsinit(&f))
+ if(pxeinit(&f) && isoinit(&f) && fsinit(&f))
print("no boot devices\n");
for(;;){
--- a/sys/src/boot/efi/fns.h
+++ b/sys/src/boot/efi/fns.h
@@ -8,6 +8,7 @@
void jump(void *pc);
int pxeinit(void **pf);
+int isoinit(void **pf);
int fsinit(void **pf);
void* (*open)(char *name);
--- /dev/null
+++ b/sys/src/boot/efi/iso.c
@@ -1,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;
+}
--- a/sys/src/boot/efi/mkfile
+++ b/sys/src/boot/efi/mkfile
@@ -10,7 +10,7 @@
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,6 +25,9 @@
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
@@ -31,7 +34,7 @@
%.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 @@
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 @@
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 @@
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.*