changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: bcm, bcm64: add support for device tree parameter passing

changeset 7309: 889b634159e5
parent 7308: 973f85a881d0
child 7310: 55d93e47a2de
author: cinap_lenrek@felloff.net
date: Thu, 25 Jul 2019 08:19:12 +0200
files: sys/src/9/bcm/bootargs.c sys/src/9/bcm/fns.h sys/src/9/bcm/main.c sys/src/9/bcm64/fns.h sys/src/9/bcm64/l.s sys/src/9/bcm64/main.c sys/src/9/bcm64/rebootcode.s
description: bcm, bcm64: add support for device tree parameter passing

the new raspberry pi 4 firmware for arm64 seems to have
broken atag support. so we now parse the device tree
structure to get the bootargs and memory configuration.
     1.1--- a/sys/src/9/bcm/bootargs.c
     1.2+++ b/sys/src/9/bcm/bootargs.c
     1.3@@ -11,29 +11,7 @@
     1.4 static char *confname[MAXCONF];
     1.5 static char *confval[MAXCONF];
     1.6 static int nconf;
     1.7-
     1.8-typedef struct Atag Atag;
     1.9-struct Atag {
    1.10-	u32int	size;	/* size of atag in words, including this header */
    1.11-	u32int	tag;	/* atag type */
    1.12-	union {
    1.13-		u32int	data[1];	/* actually [size-2] */
    1.14-		/* AtagMem */
    1.15-		struct {
    1.16-			u32int	size;
    1.17-			u32int	base;
    1.18-		} mem;
    1.19-		/* AtagCmdLine */
    1.20-		char	cmdline[1];	/* actually [4*(size-2)] */
    1.21-	};
    1.22-};
    1.23-
    1.24-enum {
    1.25-	AtagNone	= 0x00000000,
    1.26-	AtagCore	= 0x54410001,
    1.27-	AtagMem		= 0x54410002,
    1.28-	AtagCmdline	= 0x54410009,
    1.29-};
    1.30+static char maxmem[11];
    1.31 
    1.32 static int
    1.33 findconf(char *k)
    1.34@@ -85,22 +63,150 @@ plan9iniinit(char *s, int cmdline)
    1.35 	}
    1.36 }
    1.37 
    1.38-void
    1.39-bootargsinit(void)
    1.40+typedef struct Devtree Devtree;
    1.41+struct Devtree
    1.42+{
    1.43+	uchar	*base;
    1.44+	uchar	*end;
    1.45+	char	*stab;
    1.46+	char	path[1024];
    1.47+};
    1.48+
    1.49+enum {
    1.50+	DtHeader	= 0xd00dfeed,
    1.51+	DtBeginNode	= 1,
    1.52+	DtEndNode	= 2,
    1.53+	DtProp		= 3,
    1.54+	DtEnd		= 9,
    1.55+};
    1.56+
    1.57+static u32int
    1.58+beget4(uchar *p)
    1.59+{
    1.60+	return (u32int)p[0]<<24 | (u32int)p[1]<<16 | (u32int)p[2]<<8 | (u32int)p[3];
    1.61+}
    1.62+
    1.63+static void
    1.64+devtreeprop(char *path, char *key, void *val, int len)
    1.65+{
    1.66+	if(strcmp(path, "/memory") == 0 && strcmp(key, "reg") == 0 && len == 3*4){
    1.67+		if(findconf("*maxmem") < 0){
    1.68+			uvlong top;
    1.69+
    1.70+			top = (uvlong)beget4((uchar*)val)<<32 | beget4((uchar*)val+4);
    1.71+			top += beget4((uchar*)val+8);
    1.72+			snprint(maxmem, sizeof(maxmem), "%#llux", top);
    1.73+			addconf("*maxmem", maxmem);
    1.74+		}
    1.75+		return;
    1.76+	}
    1.77+	if(strcmp(path, "/chosen") == 0 && strcmp(key, "bootargs") == 0){
    1.78+		if(len > BOOTARGSLEN)
    1.79+			len = BOOTARGSLEN;
    1.80+		memmove(BOOTARGS, val, len);
    1.81+		plan9iniinit(BOOTARGS, 1);
    1.82+		return;
    1.83+	}
    1.84+}
    1.85+
    1.86+static uchar*
    1.87+devtreenode(Devtree *t, uchar *p, char *cp)
    1.88 {
    1.89-	static char maxmem[11];
    1.90-	char x, *e;
    1.91+	uchar *e = (uchar*)t->stab;
    1.92+	char *s;
    1.93+	int n;
    1.94+
    1.95+	if(p+4 > e || beget4(p) != DtBeginNode)
    1.96+		return nil;
    1.97+	p += 4;
    1.98+	if((s = memchr((char*)p, 0, e - p)) == nil)
    1.99+		return nil;
   1.100+	n = s - (char*)p;
   1.101+	cp += n;
   1.102+	if(cp >= &t->path[sizeof(t->path)])
   1.103+		return nil;
   1.104+	memmove(cp - n, (char*)p, n);
   1.105+	*cp = 0;
   1.106+	p += (n + 4) & ~3;
   1.107+	while(p+12 <= e && beget4(p) == DtProp){
   1.108+		n = beget4(p+4);
   1.109+		if(p + 12 + n > e)
   1.110+			return nil;
   1.111+		s = t->stab + beget4(p+8);
   1.112+		if(s < t->stab || s >= (char*)t->end
   1.113+		|| memchr(s, 0, (char*)t->end - s) == nil)
   1.114+			return nil;
   1.115+		devtreeprop(t->path, s, p+12, n);
   1.116+		p += 12 + ((n + 3) & ~3);
   1.117+	}
   1.118+	while(p+4 <= e && beget4(p) == DtBeginNode){
   1.119+		*cp = '/';
   1.120+		p = devtreenode(t, p, cp+1);
   1.121+		if(p == nil)
   1.122+			return nil;
   1.123+	}
   1.124+	if(p+4 > e || beget4(p) != DtEndNode)
   1.125+		return nil;
   1.126+	return p+4;
   1.127+}
   1.128+
   1.129+static int
   1.130+parsedevtree(uchar *base, uintptr len)
   1.131+{
   1.132+	Devtree t[1];
   1.133+	u32int total;
   1.134+
   1.135+	if(len < 28 || beget4(base) != DtHeader)
   1.136+		return -1;
   1.137+	total = beget4(base+4);
   1.138+	if(total < 28 || total > len)
   1.139+		return -1;
   1.140+	t->base = base;
   1.141+	t->end = t->base + total;
   1.142+	t->stab = (char*)base + beget4(base+12);
   1.143+	if(t->stab >= (char*)t->end)
   1.144+		return -1;
   1.145+	devtreenode(t, base + beget4(base+8), t->path);
   1.146+	return  0;
   1.147+}
   1.148+
   1.149+typedef struct Atag Atag;
   1.150+struct Atag {
   1.151+	u32int	size;	/* size of atag in words, including this header */
   1.152+	u32int	tag;	/* atag type */
   1.153+	union {
   1.154+		u32int	data[1];	/* actually [size-2] */
   1.155+		/* AtagMem */
   1.156+		struct {
   1.157+			u32int	size;
   1.158+			u32int	base;
   1.159+		} mem;
   1.160+		/* AtagCmdLine */
   1.161+		char	cmdline[1];	/* actually [4*(size-2)] */
   1.162+	};
   1.163+};
   1.164+
   1.165+enum {
   1.166+	AtagNone	= 0x00000000,
   1.167+	AtagCore	= 0x54410001,
   1.168+	AtagMem		= 0x54410002,
   1.169+	AtagCmdline	= 0x54410009,
   1.170+};
   1.171+
   1.172+static int
   1.173+parseatags(char *base, uintptr len)
   1.174+{
   1.175+	char x, *e = base;
   1.176 	Atag *a;
   1.177 
   1.178-	e = BOOTARGS;
   1.179+	if(e+8 > base+len)
   1.180+		return -1;
   1.181 	a = (Atag*)e;
   1.182-	if(a->tag != AtagCore){
   1.183-		plan9iniinit(e, 0);
   1.184-		return;
   1.185-	}
   1.186+	if(a->tag != AtagCore)
   1.187+		return -1;
   1.188 	while(a->tag != AtagNone){
   1.189 		e += a->size * sizeof(u32int);
   1.190-		if(a->size < 2 || e < (char*)a || e > &BOOTARGS[BOOTARGSLEN])
   1.191+		if(a->size < 2 || e < (char*)a || e > base+len)
   1.192 			break;
   1.193 		switch(a->tag){
   1.194 		case AtagMem:
   1.195@@ -116,10 +222,32 @@ bootargsinit(void)
   1.196 			*e = x;
   1.197 			break;
   1.198 		}
   1.199-		if(e > &BOOTARGS[BOOTARGSLEN-8])
   1.200+		if(e+8 > base+len)
   1.201 			break;
   1.202 		a = (Atag*)e;
   1.203 	}
   1.204+	return 0;
   1.205+}
   1.206+
   1.207+void
   1.208+bootargsinit(uintptr pa)
   1.209+{
   1.210+	uintptr len;
   1.211+
   1.212+	/*
   1.213+	 * kernel gets DTB/ATAGS pointer in R0 on entry
   1.214+	 */
   1.215+	if(pa != 0 && (len = cankaddr(pa)) != 0){
   1.216+		void *va = KADDR(pa);
   1.217+		if(parseatags(va, len) == 0 || parsedevtree(va, len) == 0)
   1.218+			return;
   1.219+	}
   1.220+
   1.221+	/*
   1.222+	 * /dev/reboot case, check CONFADDR
   1.223+	 */
   1.224+	if(parseatags(BOOTARGS, BOOTARGSLEN) != 0)
   1.225+		plan9iniinit(BOOTARGS, 0);
   1.226 }
   1.227 
   1.228 char*
     2.1--- a/sys/src/9/bcm/fns.h
     2.2+++ b/sys/src/9/bcm/fns.h
     2.3@@ -5,7 +5,7 @@ Dirtab*	addarchfile(char*, int, long(*)(
     2.4 extern void archreboot(void);
     2.5 extern void archreset(void);
     2.6 extern void armtimerset(int);
     2.7-extern void bootargsinit(void);
     2.8+extern void bootargsinit(uintptr);
     2.9 extern void cachedwbinv(void);
    2.10 extern void cachedwbse(void*, int);
    2.11 extern void cachedwbinvse(void*, int);
     3.1--- a/sys/src/9/bcm/main.c
     3.2+++ b/sys/src/9/bcm/main.c
     3.3@@ -85,7 +85,7 @@ main(void)
     3.4 	memset(edata, 0, end - edata);	/* clear bss */
     3.5 	mach0init();
     3.6 	quotefmtinstall();
     3.7-	bootargsinit();
     3.8+	bootargsinit(0);
     3.9 	confinit();		/* figures out amount of memory */
    3.10 	xinit();
    3.11 	uartconsinit();
     4.1--- a/sys/src/9/bcm64/fns.h
     4.2+++ b/sys/src/9/bcm64/fns.h
     4.3@@ -163,7 +163,7 @@ extern void vgpinit(void);
     4.4 extern void vgpset(uint port, int on);
     4.5 
     4.6 /* bootargs */
     4.7-extern void bootargsinit(void);
     4.8+extern void bootargsinit(uintptr);
     4.9 extern char *getconf(char *name);
    4.10 extern void setconfenv(void);
    4.11 extern void writeconf(void);
     5.1--- a/sys/src/9/bcm64/l.s
     5.2+++ b/sys/src/9/bcm64/l.s
     5.3@@ -5,6 +5,8 @@
     5.4 #define	SYSREG(op0,op1,Cn,Cm,op2)	SPR(((op0)<<19|(op1)<<16|(Cn)<<12|(Cm)<<8|(op2)<<5))
     5.5 
     5.6 TEXT _start(SB), 1, $-4
     5.7+	MOV	R0, R26		/* save */
     5.8+
     5.9 	MOV	$setSB-KZERO(SB), R28
    5.10 	BL	svcmode<>(SB)
    5.11 
    5.12@@ -55,6 +57,7 @@ TEXT _start(SB), 1, $-4
    5.13 	WFE
    5.14 	BL	mmuenable<>(SB)
    5.15 
    5.16+	MOV	R26, R0
    5.17 	MOV	$0, R26
    5.18 	ORR	$KZERO, R27
    5.19 	MSR	R27, TPIDR_EL1
    5.20@@ -72,11 +75,6 @@ TEXT sev(SB), 1, $-4
    5.21 	WFE
    5.22 	RETURN
    5.23 
    5.24-TEXT PUTC(SB), 1, $-4
    5.25-	MOVWU $(0x3F000000+0x215040), R14
    5.26-	MOVB R0, (R14)
    5.27-	RETURN
    5.28-
    5.29 TEXT svcmode<>(SB), 1, $-4
    5.30 	MSR	$0xF, DAIFSet
    5.31 	MRS	CurrentEL, R0
     6.1--- a/sys/src/9/bcm64/main.c
     6.2+++ b/sys/src/9/bcm64/main.c
     6.3@@ -151,14 +151,16 @@ confinit(void)
     6.4 
     6.5 	if(p = getconf("*maxmem"))
     6.6 		memsize = strtoul(p, 0, 0) - PHYSDRAM;
     6.7-	if (memsize < 16*MB)		/* sanity */
     6.8-		memsize = 16*MB;
     6.9+	if (memsize < 512*MB)		/* sanity */
    6.10+		memsize = 512*MB;
    6.11 	getramsize(&conf.mem[0]);
    6.12 	if(conf.mem[0].limit == 0){
    6.13 		conf.mem[0].base = PHYSDRAM;
    6.14 		conf.mem[0].limit = PHYSDRAM + memsize;
    6.15 	}else if(p != nil)
    6.16 		conf.mem[0].limit = conf.mem[0].base + memsize;
    6.17+	if (conf.mem[0].limit > PHYSDRAM + soc.dramsize)
    6.18+		conf.mem[0].limit = PHYSDRAM + soc.dramsize;
    6.19 
    6.20 	conf.npage = 0;
    6.21 	pa = PADDR(PGROUND((uintptr)end));
    6.22@@ -239,21 +241,18 @@ mpinit(void)
    6.23 	extern void _start(void);
    6.24 	int i;
    6.25 
    6.26+	for(i = 1; i < conf.nmach; i++){
    6.27+		MACHP(i)->machno = i;
    6.28+		cachedwbinvse(MACHP(i), MACHSIZE);
    6.29+	}
    6.30 	for(i = 0; i < MAXMACH; i++)
    6.31-		((uintptr*)SPINTABLE)[i] = 0;
    6.32-
    6.33-	for(i = 1; i < conf.nmach; i++)
    6.34-		MACHP(i)->machno = i;
    6.35+		((uintptr*)SPINTABLE)[i] = i < conf.nmach ? PADDR(_start) : 0;
    6.36+	cachedwbinvse((void*)SPINTABLE, MAXMACH*8);
    6.37 
    6.38-	coherence();
    6.39-
    6.40-	for(i = 1; i < conf.nmach; i++)
    6.41-		((uintptr*)SPINTABLE)[i] = PADDR(_start);
    6.42-
    6.43-	cachedwbinvse((void*)SPINTABLE, MAXMACH*8);
    6.44 	sev();
    6.45 	delay(100);
    6.46 	sev();
    6.47+
    6.48 	synccycles();
    6.49 
    6.50 	for(i = 0; i < MAXMACH; i++)
    6.51@@ -261,7 +260,7 @@ mpinit(void)
    6.52 }
    6.53 
    6.54 void
    6.55-main(void)
    6.56+main(uintptr arg0)
    6.57 {
    6.58 	machinit();
    6.59 	if(m->machno){
    6.60@@ -278,7 +277,7 @@ main(void)
    6.61 		return;
    6.62 	}
    6.63 	quotefmtinstall();
    6.64-	bootargsinit();
    6.65+	bootargsinit(arg0);
    6.66 	confinit();
    6.67 	xinit();
    6.68 	printinit();
    6.69@@ -313,7 +312,6 @@ rebootjump(void *entry, void *code, ulon
    6.70 {
    6.71 	void (*f)(void*, void*, ulong);
    6.72 
    6.73-	intrsoff();
    6.74 	intrcpushutdown();
    6.75 
    6.76 	/* redo identity map */
    6.77@@ -322,6 +320,7 @@ rebootjump(void *entry, void *code, ulon
    6.78 	/* setup reboot trampoline function */
    6.79 	f = (void*)REBOOTADDR;
    6.80 	memmove(f, rebootcode, sizeof(rebootcode));
    6.81+
    6.82 	cachedwbinvse(f, sizeof(rebootcode));
    6.83 	cacheiinvse(f, sizeof(rebootcode));
    6.84 
    6.85@@ -363,6 +362,7 @@ reboot(void *entry, void *code, ulong si
    6.86 	/* stop the clock (and watchdog if any) */
    6.87 	clockshutdown();
    6.88 	wdogoff();
    6.89+	intrsoff();
    6.90 
    6.91 	/* off we go - never to return */
    6.92 	rebootjump(entry, code, size);
     7.1--- a/sys/src/9/bcm64/rebootcode.s
     7.2+++ b/sys/src/9/bcm64/rebootcode.s
     7.3@@ -44,6 +44,11 @@ TEXT _start(SB), 1, $-4
     7.4 
     7.5 	BL	cachedwbinv(SB)
     7.6 	BL	cacheiinv(SB)
     7.7+
     7.8+	MOVWU	$0, R0
     7.9+	MOVWU	$0, R1
    7.10+	MOVWU	$0, R2
    7.11+	MOVWU	$0, R3
    7.12 _wait:
    7.13 	WFE
    7.14 	MOV	(R27), LR