diff --git a/Makefile b/Makefile index 5461ce9..2920007 100644 --- a/Makefile +++ b/Makefile @@ -773,7 +773,18 @@ $(BUILD)/cmd/%: cmd/%/main.c $(ULIB) $(LD) $(LDFLAGS) $(LD_LOWBASE) -e _start -Ttext 0x4000 -o $@ $(BUILD)/cmd/$*.o $(ULIB) $(OBJCOPY) -S $@ +# rm before cp, and it is not tidiness. +# +# toybox installs its 236 applets as hard links to one multicall binary, and +# some of those names collide with first-party programs here -- /bin/ping is +# both. `cp` onto an existing hard link writes *through* it, so copying this +# program over the applet of the same name replaced the contents of the shared +# inode, and every one of the 236 links became this program. `cat` ran ping. +# +# It was invisible until the applets became links: while they were separate +# copies, overwriting one affected exactly one. $(SYSROOT)/bin/%: $(BUILD)/cmd/% | $(SYSROOT)/bin + rm -f $@ cp $< $@ chmod 755 $@ @@ -971,12 +982,19 @@ $(BUILD)/sysroot.stamp: sysroot-install # - build/fs.img is no longer built by anything, since SchFS became the root, # so pointing at it meant QEMU refused to start at all; # - at FSSIZE blocks it would now be ~600 MB, because BSIZE went from 1024 to -# 4096. 16 MB is plenty to read one block from. +# 4096. The size is load-bearing: tools/windows/bootcheck.ps1 asserts on +# READ CAPACITY returning 32768 sectors of 512 bytes, which is this. +# +# --exclude bin, because this image exists to prove the USB driver can read +# a block and for no other reason. mkfs writes each hard link as its own +# copy, so once toybox's 236 applets became links to one binary the /bin +# tree expanded to more than 60 MB on the way in -- 236 copies of something +# nothing here will ever execute. USBSTICK = $(BUILD)/usbstick.img $(USBSTICK): $(MKFS) $(BUILD)/sysroot.stamp @mkdir -p $(BUILD) @rm -f $@ - $(MKFS) $@ --size 4096 --sysroot $(SYSROOT) + $(MKFS) $@ --size 4096 --exclude bin --sysroot $(SYSROOT) usbstick: $(USBSTICK) diff --git a/ports/toybox/Makefile b/ports/toybox/Makefile index 3e9ff53..2d7d786 100644 --- a/ports/toybox/Makefile +++ b/ports/toybox/Makefile @@ -10,6 +10,18 @@ include ../mk/port.mk +# Applets SchOS provides itself, which toybox must not link over. +# +# The two collide by name, and the collision is worse than a duplicate: the +# applets are hard links to one multicall binary, so whichever install runs +# second wins *for all 236 of them*. Installing first-party ping over the +# applet replaced the shared inode and every applet became ping; installing +# the applet over first-party ping put it back and lost the real one. +# +# SchOS's ping talks to its own lwIP stack and knows there is no resolver yet. +# toybox's would be the wrong answer even if it worked. +TOYBOX_SKIP = ping + TOYBOX_VERSION := 0.8.12 TOYBOX_URL := http://landley.net/toybox/downloads/toybox-$(TOYBOX_VERSION).tar.gz TOYBOX_SHA256 := ad88a921133ae2231d9f2df875ec0bd42af4429145caea7d7db9e02208a6fd2e @@ -67,6 +79,7 @@ $(BUILDDIR)/toybox.installed: $(BUILDDIR)/toybox | $(SYSROOT)/bin cp $< $(SYSROOT)/bin/toybox chmod 755 $(SYSROOT)/bin/toybox @for a in $$($(BUILDDIR)/toybox); do \ + case " $(TOYBOX_SKIP) " in *" $$a "*) continue ;; esac; \ rm -f $(SYSROOT)/bin/"$$a"; \ ln $(SYSROOT)/bin/toybox $(SYSROOT)/bin/"$$a" 2>/dev/null \ || cp $< $(SYSROOT)/bin/"$$a"; \