git: 9front

Download patch

ref: cd2263f517e4be1f60c9f8efc13656cb70da7d0f
parent: 0ab83df844a2c9dd23d02b145667ed7dcf84378b
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.* 
--