Two reports, and the first one was not an F8 bug at all.
**Choosing "Boot SchOS (verbose)" appeared to do nothing.** The menu worked,
the flag crossed, and the kernel really did boot verbose -- and then the
machine *reset* partway through and the second boot was quiet. So what anybody
ended up looking at was an ordinary boot, which reads as "verbose is broken".
PROBE before startothers, ncpu=2 <- verbose boot
SchOS UEFI loader <- the firmware, again
PROBE before startothers, ncpu=2 <- quiet boot
PROBE after startothers
mpmain() opened with
kinfo("cpu%d: starting\n", cpunum());
enable_sse();
idtinit();
and the order is the bug. enable_sse() clears CR0.EM; until it runs, *any* SSE
instruction on that CPU faults, and the kernel is not built with -mno-sse, so
the compiler emits them freely for struct copies and inline memset. idtinit()
loads that CPU's IDT; until it runs there is nowhere for a fault to go. So the
#UD is not a panic -- it is a double fault with no handler, then a triple
fault, then the firmware comes back up. A triple fault prints nothing, which is
why there was no last line to go on.
**Why only on a verbose boot**, which is what disguised it as an F8 problem:
kinfo() is log-only when the boot is quiet, so the work is a few bytes into a
ring and no XMM is involved. A verbose boot renders that same line through the
TrueType rasteriser, and that is where the SSE lands.
Setup first, announcement second. The general rule, stated where the next
person will meet it: a processor announces that it is up after it is able to
run, not before.
Verbose now boots once and puts the whole log on the screen -- `verbose boot:`
lines, `cpu1: starting`, the mount, `schinit: ready`, the jobs starting -- which
is what F8 was for and what a machine with no serial port needs.
**And vgpud drew a test card.** Three colour bands, four gradients, a
checkerboard, and the driver's own pid in binary along the bottom edge. That
was scaffolding for hybrid.md's H2 and H3: a screenshot had to answer "did a
*userspace process* put this here", and "did the driver come back" needed a
restarted instance to look different from one that never stopped. Both
milestones closed a while ago and the test card stayed, so a second display
showed something garish with nothing to explain it.
It draws the Shift mark on SCH_BG now, from the same include/logo.h the loader
splash and the kernel console use. That answers the same question a black
screen cannot -- something is driving this device -- as the system rather than
as a test rig.
Also: vgpud's "no control socket" line is vputs, not puts. It is progress, not
news, and it was printing on the console of every quiet boot.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Guru and SchCotie are gone. Shift is the only mark, and the crash screen draws
it where the face used to be.
Guru was an icon -- a pictogram with a face, denoting one state -- that lived
on the crash screen and nowhere else. Its argument was identity: `:(` is
recognisably Microsoft's, and a crash screen is the single screenshot most
likely to leave the machine, so it is the worst place to be wearing somebody
else's face. That part holds, and it is kept in the branding README because it
is the argument against any second mark. What does not follow is that the
answer is a *new* mark. Shift already signs the system, it is already what the
machine drew on the splash it started with, and a reader who has seen it twice
before the crash recognises it faster than a face they have never seen.
SchCotie was a mascot, and never existed: the file said so itself under "what
this does not cover". A brief for a character nobody is about to draw is not
worth carrying.
So `draw_guru()` and its SVG-space geometry leave panic.c, the two `guru.svg`
files are deleted, and PSOGM calls gfx_draw_logo() -- the same include/logo.h
mask the loader splash and the boot console composite. At its native 128 px:
there is no resampler in the crash path, and the face was scalable in a place
that only ever drew it at one size.
The name stays. "Purple Screen of Guru Meditation" is the Amiga nod, which
panic.c's own header already called out as a separate thing from the mark.
**And taking the screenshot to check it caught a regression from the TTF
console work.** `gfx_draw_char()` -- the pixel-positioned path, which only
PSOGM uses -- still walked `font_data[c][row]` for `row < CHAR_HEIGHT`.
font_data has exactly 16 rows per glyph; CHAR_HEIGHT is the *TrueType* cell
height now, about 21. So every line of the crash report drew five rows of the
next character's bitmap underneath itself, and it looked like each line had
been printed twice. The grid path had been updated when the cell size stopped
being a constant; this one had not, because nothing routine draws text in pixel
coordinates. Both go through one draw_glyph_px() now, and the bitmap's own
geometry is spelled BITMAP_W/BITMAP_H so it cannot be mistaken for a cell size
again.
Two stale claims corrected while in there, in panic.c's header and in
graphics.md: PSOGM has not dimmed-and-floated over the old screen for a while
-- it clears to full purple, and the file's own code comment says why -- and
there is no longer "a face that is obviously a cartoon".
The website's crash section shows the mark in flat white rather than its own
violets, which is what the kernel actually draws: PSOGM composites a coverage
mask in one colour, and those violets sit close enough to #4B1D9A to
half-disappear against it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two ANSI bugs, both found by running fastfetch rather than by reading the
parser, and both invisible to anything that spells its escapes out in full.
ESC[m with no parameters means ESC[0m. ECMA-48 is explicit that an omitted
parameter takes its default and SGR's default is 0, and sgr() iterated its
parameter list -- which is empty in exactly that case, so the loop body never
ran and the reset was silently dropped.
Programs emit the bare form constantly. fastfetch writes "\x1b[32m1%\x1b[m", so
everything after the first coloured character stayed green forever. With a
background colour it is much worse: its palette swatch sets a white background
and resets, the reset did nothing, and the console went white-on-white and
stayed there -- filling the screen with white rectangles as it scrolled, which
looks like a corrupted framebuffer rather than one missing branch.
OSC sequences were not a state at all, so ESC ] fell through and the payload
printed as text: a hyperlinked path arrived as "Disk (]8;;file:///\]8;;\)".
Nothing here acts on an operating-system command -- there is no window title and
no hyperlink to follow -- but *discarding* one is not optional, because the
alternative is printing somebody's URL into the middle of their output. ESC \
ends it, and an ESC followed by anything else is handed back to the escape state
rather than eaten, so a malformed OSC does not swallow the sequence after it.
Verified by screendumping the framebuffer after two consecutive fastfetch runs:
identical output both times, near-white coverage down from most of the screen to
2% (the palette swatch's own white cell), and the disk line reading "Disk (/)".
Also installs docs/branding/Ascii/ascii_50.txt as /usr/share/schos/logo.txt --
Shift as characters, at the width that leaves room for an info block on an
80-column console. Installed from the branding directory rather than copied into
sysroot by hand, so there is one source.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2
PSOGM drew ":(" -- two dots and a parenthesis. It now draws Guru, the icon from
docs/branding/: a chamfered head with two eye knockouts and a flat mouth, in the
:| register.
The old reasoning is kept in the file rather than deleted, because it is the
thing being traded away: ":(" was "legible as a mood without being a picture of
anything, and does not pretend the machine has feelings about what just
happened." That is a real argument and a face is a louder claim. What it buys is
identity -- ":(" is recognisably Microsoft's, and a crash screen is the single
screenshot most likely to leave the machine, so it is the worst place to be
wearing somebody else's face. The octagon also quotes the chamfered corners of
the old SchOS letterforms, which is the only part of that mark still in use.
Still drawn from primitives, for the original reason: it scales with the display
and costs no space in the kernel image. A scanline fill for the head, two
rectangles and one more knocked out of it -- no allocation, no locks, nothing
that can fail halfway, which is the whole constraint of panic context. The
geometry is expressed in the same 200-unit box docs/branding/guru.svg uses so
the two cannot drift without somebody editing a number on purpose.
The eyes and mouth are knocked out of the head rather than drawn on top of it,
which is what keeps them legible small: a hole in a solid reads at sizes a
stroke does not.
Verified by crashing on purpose -- echo c > /proc/sysrq -- and screendumping the
framebuffer through the QEMU monitor. The serial report still says ":(", and
should: Guru cannot be drawn in ASCII, and a mood marker in a log is not the
icon.
Separately, and found by looking at the boot splash rather than at the code:
boot/common/ui.c includes logo.h, theme.h and font.h, and the Makefile rule for
the loader listed none of them. A new logo therefore did not rebuild the loader.
The splash had been drawing a mask compiled six hours earlier while `make`
reported nothing to do, and the only symptom was a boot screen quietly
disagreeing with the kernel about what the logo is. The kernel half never showed
it because those objects are built with -MD -MP and track their own headers.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2
Shift is the logo, Guru is the icon, SchCotie is the mascot, and the difference
between them is not stylistic. An icon works once, at one size, in one state. A
mascot has to be able to *do* things -- confused, pleased, asleep, seen from
behind -- which is why it costs more and is drawn last. Written down because
this is exactly the kind of decision that gets re-derived badly.
Assets/ becomes docs/branding/, which also fixes two things:
* Filenames had spaces in them, so every reference needed quoting. They are
lowercase and hyphenated now.
* Assets/ held hand-written SVG and generated PNG in one directory, which is
the one rule docs/guides/layout.md states.
The guide records what was previously only in people's heads:
* The constraint everything answers to -- include/logo.h is a 128x128
single-channel coverage mask, so a mark has to survive as a solid shape in
one colour and be recognisable at 24 px. Colour is the last decision, never
the first.
* Guru's purple is load-bearing. PSOGM_BG #4B1D9A is deliberately not the
accent #7C5CFF, and theme.h's rule is that the full-bleed purple belongs
entirely to failure. If Guru appears in accent violet on a sticker, the deep
purple stops meaning "the machine stopped" -- and it is the only colour in
the system that means anything.
* Why shift-mask.svg is a separate file from shift.svg. mklogo.py reads ink as
(255 - luminance) * alpha, so tones survive as coverage and the relationship
inverts: darkest here is brightest on screen. Copying the violet fills would
light the object from below.
* Why a raster is committed beside its SVG. inkscape is not a build
prerequisite, so requiring a vector rasteriser would break the build on most
hosts for a file that changes about once a year.
* That the BSD daemon is copyrighted and SchCotie must be drawn from the
concept rather than from Beastie. A daemon is a Greek daimon and a Unix
background process; neither is ownable. The pitchfork, the sneakers and that
face are.
Format rule: SVG, or PNG at high resolution with no lossy compression, nothing
else. SVG is the source of truth for every mark and a raster is generated from
it, never edited.
include/logo.h regenerates byte-identical from the new path -- only the source
comment differs. The two old wordmark SVGs were deleted outside this session and
are left deleted; their PNGs are kept as superseded-*.png for reference.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2