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>
182 lines
8.3 KiB
Markdown
182 lines
8.3 KiB
Markdown
# Branding
|
||
|
||
One mark.
|
||
|
||
| | | |
|
||
|---|---|---|
|
||
| **Shift** | *the logo* | An abstract mark. Non-human, non-animal. Signs the system. |
|
||
|
||
There were three. **Guru**, an icon — a pictogram with a face, denoting one
|
||
state — lived on the crash screen and nowhere else. **SchCotie**, a mascot —
|
||
a character with a body, poses and expressions — was a brief and was never
|
||
drawn. Both are gone for now, and may come back.
|
||
|
||
The reasoning that retired Guru is worth keeping, because it is the argument
|
||
against any second mark. Guru existed to give the crash screen an 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. 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 went for a simpler reason: **a mascot has to be able to do things.**
|
||
An icon works once, at one size, in one state. A character has to work
|
||
confused, pleased, asleep and from behind — which is why it costs more, and why
|
||
a brief for one is not worth carrying until somebody is going to draw it.
|
||
|
||
---
|
||
|
||
## The one constraint everything answers to
|
||
|
||
**The kernel draws its mark as a 128×128 single-channel coverage mask.**
|
||
`include/logo.h` holds no colour at all — two pixels per byte, sixteen levels of
|
||
ink — and the kernel composites it in whatever `include/theme.h` says.
|
||
|
||
So any mark that will end up there has to survive as **a solid shape in one
|
||
colour at 128 px, and be recognisable at 24**. That rules out hairlines, thin
|
||
rings and anything that depends on a gradient to read. The mark this replaced
|
||
failed on all three counts.
|
||
|
||
Colour is therefore the *last* decision, never the first. Design the silhouette,
|
||
then colour it.
|
||
|
||
---
|
||
|
||
## Shift — the logo
|
||
|
||
`shift.svg`
|
||
|
||
Three slabs, displaced: the layer diagram in
|
||
[../architecture/README.md](../architecture/README.md) as a solid object, and
|
||
the kernel's name (**SchIFT**) as a shape.
|
||
|
||
- **Any colour.** This is a fact about the pipeline, not a preference — the
|
||
coverage mask carries none, so the loader draws it in metal and the kernel in
|
||
the theme accent, from the same bytes.
|
||
- **With or without a wordmark.** Set "SchOS" beside it in **Roboto Bold**,
|
||
which is already in the tree (`ports/Roboto`), already Apache-2.0, and already
|
||
in `NOTICE`.
|
||
- Non-human and non-animal, permanently. If a character is ever drawn it gets
|
||
its own mark; a logo that starts growing a face has taken that job.
|
||
|
||
---
|
||
|
||
## Colour
|
||
|
||
From `include/theme.h`, which is the source of truth. Nothing here restates a
|
||
value it does not already define.
|
||
|
||
| | | |
|
||
|---|---|---|
|
||
| `SCH_BG` | `#0C0E13` | Ground. Near-black with a blue cast, because pure black reads as "switched off". |
|
||
| `SCH_FG` | `#E6E8EC` | Primary text |
|
||
| `SCH_DIM` | `#707784` | Secondary |
|
||
| `SCH_ACCENT` | `#7C5CFF` | The one accent. Shift, and anything calm. |
|
||
| `PSOGM_BG` | `#4B1D9A` | **Failure only.** The crash screen's ground and nothing else's. |
|
||
|
||
`PSOGM_BG` is deliberately **not** the accent. `theme.h` states the rule it
|
||
enforces:
|
||
|
||
> normal states are calm and dark; only failure is loud. PSOGM keeps the
|
||
> full-bleed purple entirely to itself, which is what makes it mean something.
|
||
|
||
If that purple ever appears on a splash, a sticker or a README header, it stops
|
||
meaning *the machine stopped* — and it is the only colour in the system that
|
||
means anything at all.
|
||
|
||
## File formats
|
||
|
||
**SVG, or PNG at high resolution with no lossy compression.** Nothing else.
|
||
|
||
No JPEG anywhere — a mark is flat colour with hard edges, which is the exact
|
||
case JPEG is worst at, and the ringing it leaves around an edge is permanent.
|
||
No screenshots of marks. No re-exports of re-exports: go back to the SVG.
|
||
|
||
**SVG is the source of truth for every mark.** A raster is something generated
|
||
from it, never edited.
|
||
|
||
## The mark as characters
|
||
|
||
`Ascii/ascii_{50,68,100,150}.txt` — Shift rendered in text at four widths, named
|
||
for the column count they fit in.
|
||
|
||
`make` installs the 50-column one as `/usr/share/schos/logo.txt`, because 50 is
|
||
what leaves room for an info block beside it on an 80-column console:
|
||
|
||
```sh
|
||
fastfetch --file-raw /usr/share/schos/logo.txt
|
||
```
|
||
|
||
Installed from here rather than copied into `sysroot/` by hand, so there is one
|
||
source and the build keeps them in step.
|
||
|
||
These are a *rendering* of the mark, not a second mark. If Shift changes they
|
||
are regenerated from it; they are not edited to taste, or the two drift and the
|
||
text one wins by being the one people see in a terminal.
|
||
|
||
## What is in here, and why a raster is committed
|
||
|
||
```
|
||
shift.svg the logo, in colour
|
||
shift-mask.svg the same geometry in greys -- see below
|
||
shift-mask.png rasterised from it, committed on purpose
|
||
uberblock.svg SchFS
|
||
superseded-*.png the old wordmark, kept for reference only
|
||
```
|
||
|
||
The pipeline is three stages:
|
||
|
||
```
|
||
shift-mask.svg --(inkscape)--> shift-mask.png --(make logo)--> include/logo.h
|
||
```
|
||
|
||
**Both intermediates are committed, and that is deliberate.** `inkscape` is not
|
||
a build prerequisite — see [../guides/building.md](../guides/building.md) — so a
|
||
build that required a vector rasteriser would stop working on most hosts for the
|
||
sake of a file that changes about once a year. The PNG is regenerated by hand
|
||
when the SVG changes, and `make logo` turns it into the header.
|
||
|
||
### Why the mask is a separate file from the logo
|
||
|
||
`tools/python/mklogo.py` reads ink as `(255 - luminance) * alpha`, so **tones
|
||
survive as coverage** rather than being flattened — and the relationship
|
||
inverts: *darkest here is brightest on screen*. Copying the violet fills from
|
||
`shift.svg` would light the object from below.
|
||
|
||
So `shift-mask.svg` is the same geometry in greys chosen for how the mask reads.
|
||
Two files sharing one geometry is a drift hazard; the `<desc>` in both says so.
|
||
If either is edited, edit both.
|
||
|
||
---
|
||
|
||
## Where each mark is actually drawn
|
||
|
||
| | |
|
||
|---|---|
|
||
| Loader splash | Shift, from `include/logo.h`, shaded per row by `metal()` in `boot/common/ui.c` — silver, not accent. |
|
||
| Kernel console / early boot | Shift, same mask, composited flat in a theme colour by `gfx_draw_logo`. |
|
||
| A display with no compositor | Shift again, drawn by `vgpud` on `SCH_BG`. It replaced a test card — colour bands, gradients, a checkerboard and the driver's pid in binary — which was scaffolding for [../plan/hybrid.md](../plan/hybrid.md)'s H2 and H3 and outlived them. The mark answers the same question a black screen cannot, *something is driving this device*, and answers it as the system rather than as a test rig. |
|
||
| PSOGM | Shift, the same mask again, by `gfx_draw_logo()` from `kernel/core/panic.c`. At its native 128 px — there is no resampler in the crash path, and the mark was only ever drawn at one size there anyway. |
|
||
| Serial crash report | `:(`, as text. The mark cannot be drawn in ASCII, and a mood marker in a log is not a mark. |
|
||
| SchFS | **Nowhere yet.** `uberblock.svg` has no consumer; it is waiting for `projects/schfs-linux/` to have a README worth heading. |
|
||
|
||
One trap, since it has already been stepped in: `boot/common/ui.c` includes
|
||
`logo.h`, `theme.h` and `font.h`, and the Makefile rule for the loader did not
|
||
list them. A new logo therefore did not rebuild the loader — `make` reported
|
||
nothing to do and the splash kept drawing a mask compiled months earlier. The
|
||
kernel half never showed the problem because those objects are built with
|
||
`-MD -MP` and track their own headers. **Changing anything in here means the
|
||
loader must actually relink**, and that needs `clang` and `lld-link`.
|
||
|
||
## What this does not cover
|
||
|
||
- **No trademark position.** These are marks the project uses, not marks anyone
|
||
has registered or defended.
|
||
- **No usage rules for third parties** — nothing says what someone else may do
|
||
with them. Worth writing before anything is published.
|
||
- **There is no icon and no mascot.** Both were removed rather than left
|
||
half-specified. If either comes back it starts from the argument at the top
|
||
of this file, not from what used to be here.
|
||
- **No wordmark lockup is specified.** "Roboto Bold beside it" is not a spacing
|
||
rule, a size ratio or a clear-space margin, and it will want to be.
|