boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs

commit c24e386d1f9da71804e861ccfa961b6db0f6d924
parent b67850fbf7de470673af34368fe0342900082d26
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Thu, 23 Apr 2026 06:54:42 -0700

Add P1 m1m bootstrap stub

Diffstat:
MMakefile | 19++++++++++++++++---
Asrc/m1m.M1 | 331+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/p1_gen.py | 6++++++
3 files changed, 353 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile @@ -77,6 +77,15 @@ OUT_DIR := build/$(ARCH) TOOLS_DIR := $(OUT_DIR)/tools COMBINED_DIR := $(OUT_DIR)/combined +ifeq ($(PROG),m1m) + ifneq ($(ARCH),aarch64) + $(error PROG=m1m is currently staged for ARCH=aarch64 only) + endif + P1_DEFS := $(OUT_DIR)/p1_m1m_aarch64.M1 +else + P1_DEFS := $(OUT_DIR)/p1_$(ARCH).M1 +endif + # stage0-posix uses mixed-case arch dirs (AArch64, AMD64) that don't match # our lowercase ARCH. Map them so build/upstream/ mirrors upstream layout. ARCH_DIR_aarch64 := AArch64 @@ -175,10 +184,10 @@ $(TOOLS_DIR)/M0 $(TOOLS_DIR)/hex2-0 $(TOOLS_DIR)/catm $(TOOLS_DIR)/hex0 $(TOOLS_ # # M0 takes a single positional input (no -f flag), so we catm the pruned p1 # with PROG_SRC first. Intermediates stay in OUT_DIR so clean picks them up. -$(OUT_DIR)/$(PROG).hex2: $(PROG_SRC) $(OUT_DIR)/p1_$(ARCH).M1 lint.sh $(TOOLS_DIR)/M0 $(TOOLS_DIR)/catm | $(OUT_DIR) $(IMAGE_STAMP) - ./lint.sh $(OUT_DIR)/p1_$(ARCH).M1 $(PROG_SRC) +$(OUT_DIR)/$(PROG).hex2: $(PROG_SRC) $(P1_DEFS) lint.sh $(TOOLS_DIR)/M0 $(TOOLS_DIR)/catm | $(OUT_DIR) $(IMAGE_STAMP) + ./lint.sh $(P1_DEFS) $(PROG_SRC) awk 'NR==FNR{for(i=1;i<=NF;i++)u[$$i]=1;next} /^DEFINE /{if($$2 in u)print;next} {print}' \ - $(PROG_SRC) $(OUT_DIR)/p1_$(ARCH).M1 > $(OUT_DIR)/p1_$(ARCH).pruned.M1 + $(PROG_SRC) $(P1_DEFS) > $(OUT_DIR)/p1_$(ARCH).pruned.M1 $(PODMAN) sh -ec ' \ cp $(OUT_DIR)/p1_$(ARCH).pruned.M1 /tmp/p1.M1 ; \ cp $(PROG_SRC) /tmp/prog.M1 ; \ @@ -308,3 +317,7 @@ clean: # no staleness risk). build/aarch64/p1_aarch64.M1 build/amd64/p1_amd64.M1 build/riscv64/p1_riscv64.M1 &: src/p1_gen.py python3 src/p1_gen.py build + +build/aarch64/p1_m1m_aarch64.M1: build/aarch64/p1_aarch64.M1 src/m1m.M1 | build/aarch64 + awk 'NR==FNR{for(i=1;i<=NF;i++)u[$$i]=1;next} /^DEFINE /{if($$2 in u)print;next} {print}' \ + src/m1m.M1 build/aarch64/p1_aarch64.M1 > $@ diff --git a/src/m1m.M1 b/src/m1m.M1 @@ -0,0 +1,331 @@ +## m1m.M1 -- bootstrap M1 macro-expander executable shell. +## +## This file is intentionally raw P1 source: no M1M macros are used to build +## the first macro expander. The executable contract matches src/m1macro.c: +## +## m1m input.M1 output.M1 +## +## Current state: argv and file I/O are real, but the expander core is still +## stubbed out with an explicit failure. Keeping the failure explicit avoids +## accidentally treating an incomplete bootstrap stage as a pass-through +## macro expander. + +DEFINE M1M_BUF_SIZE 00400000 +DEFINE O_WRONLY_CREAT_TRUNC 41020000 +DEFINE MODE_0644 A4010000 +DEFINE AT_FDCWD 9CFFFFFF +DEFINE ZERO32 '0000000000000000000000000000000000000000000000000000000000000000' + +:_start + ## Kernel entry stack: [sp+0]=argc, [sp+8]=argv[0], + ## [sp+16]=argv[1], [sp+24]=argv[2]. + ld_r0,sp,0 + li_r1 %3 + li_br &err_usage + blt_r0,r1 + + ## Preserve output path in r6 while opening and reading input. + ld_r6,sp,24 + + ## openat(AT_FDCWD, argv[1], O_RDONLY=0, mode=0) + ld_r2,sp,16 + li_r0 sys_openat + li_r1 AT_FDCWD + li_r3 %0 + li_r4 %0 + syscall + + li_br &err_open_input + bltz_r0 + mov_r5,r0 + + ## Read the complete input file into m1m_input_buf. + li_r7 %0 +:read_loop + li_r3 M1M_BUF_SIZE + li_br &read_done + beq_r7,r3 + + li_r0 sys_read + mov_r1,r5 + li_r2 &m1m_input_buf + add_r2,r2,r7 + li_r3 M1M_BUF_SIZE + sub_r3,r3,r7 + syscall + + li_br &read_done + beqz_r0 + li_br &err_read + bltz_r0 + + add_r7,r7,r0 + li_br &read_loop + b + +:read_done + li_r3 M1M_BUF_SIZE + li_br &err_input_too_big + beq_r7,r3 + + ## The parser/expander will fill m1m_output_buf and set r7 to its + ## output byte count. Until that core lands, fail loudly. + li_br &err_not_implemented + b + + ## Unreachable until the expander core branches here. +:write_output + ## openat(AT_FDCWD, argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0644) + li_r0 sys_openat + li_r1 AT_FDCWD + mov_r2,r6 + li_r3 O_WRONLY_CREAT_TRUNC + li_r4 MODE_0644 + syscall + + li_br &err_open_output + bltz_r0 + mov_r4,r0 + + ## Write r7 bytes from m1m_output_buf. + li_r5 %0 +:write_loop + li_br &write_done + beq_r5,r7 + + li_r0 sys_write + mov_r1,r4 + li_r2 &m1m_output_buf + add_r2,r2,r5 + sub_r3,r7,r5 + syscall + + li_br &err_write + bltz_r0 + li_br &err_write + beqz_r0 + + add_r5,r5,r0 + li_br &write_loop + b + +:write_done + li_r0 sys_exit + li_r1 %0 + syscall + +:err_usage + li_r1 &msg_usage + li_r2 %29 + li_br &fatal + b + +:err_open_input + li_r1 &msg_open_input + li_r2 %25 + li_br &fatal + b + +:err_read + li_r1 &msg_read + li_r2 %20 + li_br &fatal + b + +:err_input_too_big + li_r1 &msg_input_too_big + li_r2 %20 + li_br &fatal + b + +:err_not_implemented + li_r1 &msg_not_implemented + li_r2 %29 + li_br &fatal + b + +:err_open_output + li_r1 &msg_open_output + li_r2 %26 + li_br &fatal + b + +:err_write + li_r1 &msg_write + li_r2 %22 + li_br &fatal + b + +## fatal(msg, len): write "m1m: " + msg to stderr and exit 1. +## Inputs: r1 = message pointer, r2 = message length. +:fatal + mov_r6,r1 + mov_r7,r2 + + li_r0 sys_write + li_r1 %2 + li_r2 &msg_prefix + li_r3 %5 + syscall + + li_r0 sys_write + li_r1 %2 + mov_r2,r6 + mov_r3,r7 + syscall + + li_r0 sys_write + li_r1 %2 + li_r2 &msg_newline + li_r3 %1 + syscall + + li_r0 sys_exit + li_r1 %1 + syscall + +:msg_prefix "m1m: " +:msg_newline " +" +:msg_usage "usage: m1m input.M1 output.M1" +:msg_open_input "failed to open input file" +:msg_read "failed to read input" +:msg_input_too_big "input file too large" +:msg_not_implemented "expander core not implemented" +:msg_open_output "failed to open output file" +:msg_write "failed to write output" + +:ELF_end + +## BSS. The ELF header maps this zero-filled region after the on-disk image. +:m1m_input_buf +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +:m1m_output_buf +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 ZERO32 +:ELF_bss_end diff --git a/src/p1_gen.py b/src/p1_gen.py @@ -1025,9 +1025,15 @@ RRR_TABLE = ( ('ADD','r6','r1','r2'), ('ADD','r6','r6','r0'), ('ADD','r7','r1','r2'), + # m1m bootstrap file I/O buffer indexing. + ('ADD','r2','r2','r5'), + ('ADD','r2','r2','r7'), ('SUB','r2','r1','r6'), ('SUB','r3','r1','r6'), ('SUB','r2','r2','r1'), # prelude length = end - start + # m1m bootstrap file I/O remaining-byte counts. + ('SUB','r3','r3','r7'), + ('SUB','r3','r7','r5'), ('REM','r1','r1','r2'), # bump-pointer + accumulator updates (originally kaem-minimal; # retained in case lisp uses them — lint catches dead entries)