Suggestion for prekern: warning messages

Pierre Pronchery <[email protected]>
Newsgroups gmane.os.netbsd.ports.x86-64
Message-ID <[email protected]>
			Hi port-amd64@,

I’d like to have opinions on a few changes I am preparing for the prekern. (Patch attached)

Basically I would like to modify print_state() to accept more contexts than just ok/fail, and sprinkle a few more warning messages:
- when no hardware entropy instruction is supported
- when the entropy file was corrupted (instead of panic, rationale: none may have been found or specified)
- when no entropy file could be loaded

I introduced a yellow “[*]" symbol for this purpose (alternative suggestions welcome).

In my tests with QEMU (5.2.0 from pkgsrc 2021Q1 on macOS Catalina amd64) no CPU entropy instruction was detected (RDRAND and RDSEED are supported). Without an entropy file, I guess it only leaves the time of boot in order to guess the seed for KASLR, which is not ideal.

On another note, it might make sense to fully clear the screen before drawing the logo; otherwise the output is mangled with that of boot(8) when switching the console to e.g. a serial port for the kernel.

Another feature I have in mind is to detect the choice of console and support serial consoles in prekern. I guess it would make it easier to debug.



Cheers!
--
khorben
patch-prekern_warnings.diff (application/octet-stream, 6.1 KB)
diff --git a/sys/arch/amd64/stand/prekern/console.c b/sys/arch/amd64/stand/prekern/console.c
index b3fc82c89e1b..752f73826e52 100644
--- a/sys/arch/amd64/stand/prekern/console.c
+++ b/sys/arch/amd64/stand/prekern/console.c
@@ -94,13 +94,24 @@ void print(char *buf)
 	print_ext(WHITE_ON_BLACK, buf);
 }
 
-void print_state(bool ok, char *buf)
+void print_state(state_t state, char *buf)
 {
 	print("[");
-	if (ok)
-		print_ext(GREEN_ON_BLACK, "+");
-	else
-		print_ext(RED_ON_BLACK, "!");
+	switch (state)
+	{
+		case STATE_NORMAL:
+			print_ext(GREEN_ON_BLACK, "+");
+			break;
+		case STATE_ERROR:
+			print_ext(RED_ON_BLACK, "!");
+			break;
+		case STATE_WARNING:
+			print_ext(YELLOW_ON_BLACK, "*");
+			break;
+		default:
+			print_ext(WHITE_ON_BLACK, "?");
+			break;
+	}
 	print("] ");
 	print(buf);
 	print("\n");
diff --git a/sys/arch/amd64/stand/prekern/elf.c b/sys/arch/amd64/stand/prekern/elf.c
index a4ee9f09f3ee..cbde65ab37df 100644
--- a/sys/arch/amd64/stand/prekern/elf.c
+++ b/sys/arch/amd64/stand/prekern/elf.c
@@ -377,7 +377,7 @@ elf_kernel_reloc(void)
 	Elf_Sym *sym;
 	size_t i, j;
 
-	print_state(true, "ELF info created");
+	print_state(STATE_NORMAL, "ELF info created");
 
 	/*
 	 * Update all symbol values with the appropriate offset.
@@ -398,7 +398,7 @@ elf_kernel_reloc(void)
 		}
 	}
 
-	print_state(true, "Symbol values updated");
+	print_state(STATE_NORMAL, "Symbol values updated");
 
 	/*
 	 * Perform relocations without addend if there are any.
@@ -427,7 +427,7 @@ elf_kernel_reloc(void)
 		}
 	}
 
-	print_state(true, "REL relocations applied");
+	print_state(STATE_NORMAL, "REL relocations applied");
 
 	/*
 	 * Perform relocations with addend if there are any.
@@ -456,7 +456,7 @@ elf_kernel_reloc(void)
 		}
 	}
 
-	print_state(true, "RELA relocations applied");
+	print_state(STATE_NORMAL, "RELA relocations applied");
 
 	/*
 	 * Get the entry point.
@@ -466,7 +466,7 @@ elf_kernel_reloc(void)
 		fatal("elf_kernel_reloc: entry point not found");
 	}
 
-	print_state(true, "Entry point found");
+	print_state(STATE_NORMAL, "Entry point found");
 
 	return ent;
 }
diff --git a/sys/arch/amd64/stand/prekern/mm.c b/sys/arch/amd64/stand/prekern/mm.c
index f7575c1e95db..c7e07403110b 100644
--- a/sys/arch/amd64/stand/prekern/mm.c
+++ b/sys/arch/amd64/stand/prekern/mm.c
@@ -148,7 +148,7 @@ mm_bootspace_mprotect(void)
 		mm_mprotect(bootspace.segs[i].va, bootspace.segs[i].sz, prot);
 	}
 
-	print_state(true, "Segments protection updated");
+	print_state(STATE_NORMAL, "Segments protection updated");
 }
 
 static size_t
@@ -439,9 +439,9 @@ mm_map_kernel(void)
 {
 	memset(&bootspace, 0, sizeof(bootspace));
 	mm_map_head();
-	print_state(true, "Head region mapped");
+	print_state(STATE_NORMAL, "Head region mapped");
 	elf_map_sections();
-	print_state(true, "Segments mapped");
+	print_state(STATE_NORMAL, "Segments mapped");
 	mm_map_boot();
-	print_state(true, "Boot region mapped");
+	print_state(STATE_NORMAL, "Boot region mapped");
 }
diff --git a/sys/arch/amd64/stand/prekern/prekern.c b/sys/arch/amd64/stand/prekern/prekern.c
index 410a12d35954..b63092dfb34a 100644
--- a/sys/arch/amd64/stand/prekern/prekern.c
+++ b/sys/arch/amd64/stand/prekern/prekern.c
@@ -286,7 +286,7 @@ init_prekern(paddr_t pa_start)
 	 */
 	init_idt();
 
-	print_state(true, "Prekern loaded");
+	print_state(STATE_NORMAL, "Prekern loaded");
 
 	/*
 	 * Init the PRNG.
@@ -308,7 +308,7 @@ init_prekern(paddr_t pa_start)
 	/*
 	 * Finally, jump into the kernel.
 	 */
-	print_state(true, "Jumping into the kernel");
+	print_state(STATE_NORMAL, "Jumping into the kernel");
 	jump_kernel(ent);
 
 	fatal("init_prekern: unreachable!");
diff --git a/sys/arch/amd64/stand/prekern/prekern.h b/sys/arch/amd64/stand/prekern/prekern.h
index fc9dd6315c9f..2fcfacce27f8 100644
--- a/sys/arch/amd64/stand/prekern/prekern.h
+++ b/sys/arch/amd64/stand/prekern/prekern.h
@@ -42,6 +42,7 @@ typedef uint64_t pte_prot_t;
 #define WHITE_ON_BLACK 0x07
 #define RED_ON_BLACK 0x04
 #define GREEN_ON_BLACK 0x02
+#define YELLOW_ON_BLACK 0x0e
 
 #define HEAD_WINDOW_BASE	(KERNBASE - NBPD_L3)
 #define HEAD_WINDOW_SIZE	NBPD_L3
@@ -49,6 +50,13 @@ typedef uint64_t pte_prot_t;
 #define KASLR_WINDOW_BASE	KERNBASE		/* max - 2GB */
 #define KASLR_WINDOW_SIZE	(2LLU * (1 << 30))	/* 2GB */
 
+typedef enum
+{
+	STATE_NORMAL = 0,
+	STATE_ERROR,
+	STATE_WARNING
+} state_t;
+
 /* -------------------------------------------------------------------------- */
 
 #define BTSEG_NONE	0
@@ -83,7 +91,7 @@ struct bootspace {
 void init_cons(void);
 void print_ext(int, char *);
 void print(char *);
-void print_state(bool, char *);
+void print_state(state_t, char *);
 void print_banner(void);
 
 /* elf.c */
diff --git a/sys/arch/amd64/stand/prekern/prng.c b/sys/arch/amd64/stand/prekern/prng.c
index 95087a3d4aa5..075aa19bc309 100644
--- a/sys/arch/amd64/stand/prekern/prng.c
+++ b/sys/arch/amd64/stand/prekern/prng.c
@@ -84,6 +84,7 @@ prng_get_entropy_file(SHA512_CTX *ctx)
 	uint8_t digest[SHA1_DIGEST_LENGTH];
 	rndsave_t *rndsave;
 	SHA1_CTX sig;
+	size_t count = 0;
 
 	biml =
 	    (struct btinfo_modulelist *)prng_lookup_bootinfo(BTINFO_MODULELIST);
@@ -98,7 +99,9 @@ prng_get_entropy_file(SHA512_CTX *ctx)
 			continue;
 		}
 		if (bi->len != sizeof(rndsave_t)) {
-			fatal("rndsave_t size mismatch");
+			print_state(STATE_WARNING,
+					"size mismatch in entropy file");
+			continue;
 		}
 		rndsave = (rndsave_t *)(vaddr_t)bi->base;
 
@@ -109,11 +112,16 @@ prng_get_entropy_file(SHA512_CTX *ctx)
 		SHA1Update(&sig, rndsave->data, sizeof(rndsave->data));
 		SHA1Final(digest, &sig);
 		if (memcmp(digest, rndsave->digest, sizeof(digest))) {
-			fatal("bad SHA1 checksum");
+			print_state(STATE_WARNING,
+					"bad SHA1 checksum in entropy file");
+			continue;
 		}
 
 		SHA512_Update(ctx, rndsave->data, sizeof(rndsave->data));
+		count++;
 	}
+	if (count == 0)
+		print_state(STATE_WARNING, "no entropy file could be loaded");
 }
 
 /*
@@ -159,6 +167,8 @@ prng_init(void)
 	has_rdseed = (descs[1] & CPUID_SEF_RDSEED) != 0;
 	cpuid(0x01, 0x00, descs);
 	has_rdrand = (descs[2] & CPUID2_RDRAND) != 0;
+	if (!has_rdseed && !has_rdrand)
+		print_state(STATE_WARNING, "No CPU entropy feature detected");
 
 	SHA512_Init(&ctx);
 	prng_get_entropy_file(&ctx);
signature.asc (application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE-----

iQIzBAEBCAAdFiEEjPEp1wC4bxBrX8svMDjL25iGlwMFAmBzqM0ACgkQMDjL25iG
lwMp4g/+POYS9KEsiGXntyd5Fd7CYTmOxc/kp9Oc1/GEvkBsGV3TfAt6vFjp7REr
0io+K68mtRyQQUM9b6WH35o7swDwMGTv9PgCxY5waGCLPGRHhbgU/gzzzR9LiD6c
IIqGnowajH+MsY02stvjtDjYP4Tl9A/gNcO7mBatHKXkbilv5XTCplbKealpGVKM
ZuVbz03DTjm9QAB7rCIB81dk5f/lHEcWH5SxiKp5lhOxVI8tZMYUvktScuSMUHtQ
NvVYriVYXzwdpocEQZ6zh6jjGHxbi+apJEGM5YnLm7S6P9laJMpxGBGe0kCeBtxB
bEpPC40vIbm5rzgllp7+DyzspyDvqMTI4s6ze049B4SuKu3D/gPwojrU/qZtrfmU
ELge4dK5rW2bLvorvu0N8wUC04IbUHemmsTP0cVs1111CB3A6OQCnZ33GVG9kotn
l5fi2HTcHBRVlHoxZyNeRJ/xx/nXXcz5DuFoeATPpD9J0IWABmkNcTVFRPIz5fQv
C0M5sFx2GYI/FlKoO9Vrq7UgOX3MnlV1kPtB/oiFy0KoEpfS2OnVaRxorBcH8/U5
rQ6CCLGTYvkBPoFN7ocGrTur7UT9OPGG6jYGoF5wQACl+gPcJ+C0Gh+tksj8JSgR
qkOwGhL1jCgciGvUnYgxErfhqXWutNxaHscwYuRS67lUWFZEDEs=
=KM7m
-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.