fix: comprehensive boot warnings and exceptions — fixable silenced, unfixable diagnosed

Build system (5 gaps hardened):
- COOKBOOK_OFFLINE defaults to true (fork-mode)
- normalize_patch handles diff -ruN format
- New 'repo validate-patches' command (25/25 relibc patches)
- 14 patched Qt/Wayland/display recipes added to protected list
- relibc archive regenerated with current patch chain

Boot fixes (fixable):
- Full ISO EFI partition: 16 MiB → 1 MiB (matches mini, BIOS hardcoded 2 MiB offset)
- D-Bus system bus: absolute /usr/bin/dbus-daemon path (was skipped)
- redbear-sessiond: absolute /usr/bin/redbear-sessiond path (was skipped)
- daemon framework: silenced spurious INIT_NOTIFY warnings for oneshot_async services (P0-daemon-silence-init-notify.patch)
- udev-shim: demoted INIT_NOTIFY warning to INFO (expected for oneshot_async)
- relibc: comprehensive named semaphores (sem_open/close/unlink) replacing upstream todo!() stubs
- greeterd: Wayland socket timeout 15s → 30s (compositor DRM wait)
- greeter-ui: built and linked (header guard unification, sem_compat stubs removed)
- mc: un-ignored in both configs, fixed glib/libiconv/pcre2 transitive deps
- greeter config: removed stale keymapd dependency from display/greeter services
- prefix toolchain: relibc headers synced, _RELIBC_STDLIB_H guard unified

Unfixable (diagnosed, upstream):
- i2c-hidd: abort on no-I2C-hardware (QEMU) — process::exit → relibc abort
- kded6/greeter-ui: page fault 0x8 — Qt library null deref
- Thread panics fd != -1 — Rust std library on Redox
- DHCP timeout / eth0 MAC — QEMU user-mode networking
- hwrngd/thermald — no hardware RNG/thermal in VM
- live preload allocation — BIOS memory fragmentation, continues on demand
This commit is contained in:
2026-05-05 20:20:37 +01:00
parent a5f97b6632
commit f31522130f
81834 changed files with 11051982 additions and 108 deletions
@@ -0,0 +1,47 @@
# Copyright (C) 2024 Stan Morris
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(setVertexCount-spiral VERSION 0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)
qt_standard_project_setup(REQUIRES 6.5)
qt_add_executable(appVertexCount
main.cpp
)
qt_add_qml_module(appVertexCount
URI VertexSpiral
VERSION 1.0
QML_FILES
Main.qml
SOURCES SpiralItem.h SpiralItem.cpp
RESOURCES README.txt
)
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
# If you are developing for iOS or macOS you should consider setting an
# explicit, fixed bundle identifier manually though.
set_target_properties(appVertexCount PROPERTIES
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appVertexCount
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
target_link_libraries(appVertexCount
PRIVATE Qt6::Quick
)
include(GNUInstallDirs)
install(TARGETS appVertexCount
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
@@ -0,0 +1,131 @@
// Copyright (C) 2024 Stan Morris
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
import QtQuick.Window
import VertexSpiral
ApplicationWindow {
id: window
property int frameCount: 0
width: spiral.width + 40
height: spiral.height + 40
visible: true
title: qsTr("QSGGeometry::setVertexCount() tester")
color: "black"
onFrameSwapped: ++window.frameCount
// Component.onCompleted: {
// // kick off animation at startup
// button.clicked()
// }
SpiralItem {
id: spiral
anchors.centerIn: parent
vertexCount: slider.value
SequentialAnimation {
id: seqAnim
loops: Animation.Infinite
onStarted: spiral.toggleMode()
NumberAnimation {
target: spiral
property: "vertexCount"
to: spiral.maxVertices
duration: 2000
}
// Do not animate down to zero!
//
// Do not set "to:" equal to "0"... use "1" to avoid QTBUG-58177,
// which regards geometries not rendering after vertex count is set 0.
//
NumberAnimation {
target: spiral
property: "vertexCount"
// Make zero to see QTBUG-58177. Hover the top-tight "Quit"
// button to see how it oddly temporarily fixes rendering.
to: 1
duration: 2000
}
ScriptAction { script: spiral.toggleMode() }
// Pause long enough for the Renderer to process geometry with zero
// vertices so QTBUG-58177 is consistently reproducible if you want
// to see its behavior.
PauseAnimation { duration: 20 }
}
}
Slider {
id: slider
anchors { left: parent.left; top: parent.top; bottom: parent.bottom }
orientation: Qt.Vertical
from: spiral.maxVertices
to: 0
value: spiral.maxVertices
focus: true
Keys.onEscapePressed: Qt.quit()
}
Column {
anchors.right: parent.right
Button { id: hiddenButton; visible: false; text: "Animate Vertex Count" }
Button {
id: button
text: hiddenButton.text
width: hiddenButton.width
Keys.onEscapePressed: Qt.quit()
onClicked: {
if (slider) {
slider.destroy();
text = "Quit";
// reset number of vertices in case user is starting from max
spiral.vertexCount = 1;
seqAnim.start();
} else {
Qt.quit();
}
}
}
Column {
id: stats
anchors.horizontalCenter: parent.horizontalCenter
component MyText: Text {
font { bold: true; pixelSize: 16 }
color: "white"
}
component Stat: Row {
id: rowRoot
property alias caption: label.text
property alias value: valueText.text
anchors.horizontalCenter: stats.horizontalCenter
width: 2*label.width
spacing: 8
MyText { id: label }
MyText { id: valueText }
}
MyText { anchors.horizontalCenter: parent.horizontalCenter; text: spiral.mode }
Stat { caption: "FPS:"; value: spiral.fps }
Timer {
id: fpsTimer
interval: 1000
repeat: true
running: stats.visible
onTriggered: {
spiral.fps = window.frameCount;
window.frameCount = 0;
}
}
}
}
}
@@ -0,0 +1,16 @@
README for setVertexCount-spiral project
This manual test project exercises QSGGeometry::setVertexCount().
The slider changes the number of vertices. Pressing the button in the
top right animates the number of vertices and toggles between using
setVertexCount() and allocate() to change the number of vertices.
While animating, the resize mode, vertex count, and frame rate are
logged to the console.
CPU utilization is always lower using setVertextCount()
top -p `pgrep appVertexCount`
Note: This app does not test indexed drawing.
@@ -0,0 +1,253 @@
// Copyright (C) 2024 Stan Morris.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QSGGeometry>
#include <QSGGeometryNode>
#include <QSGVertexColorMaterial>
#include <cmath>
#include <numbers>
#include "SpiralItem.h"
namespace {
std::array<int, 4> getParts(const QColor &color) {
return {color.red(), color.green(), color.blue(), color.alpha()};
}
using ColorPalette = std::array<QColor, 3>;
auto allocPalette = ColorPalette { QColor("aqua"), QColor("deepskyblue"), QColor("yellow") };
auto setVCPalette = ColorPalette { QColor("yellow"), QColor("orange"), QColor("white") };
}
SpiralItem::SpiralItem()
{
setFlag(QQuickItem::ItemHasContents);
setWidth(960);
setHeight(960);
connect(this, &SpiralItem::vertexCountChanged,
this, &QQuickItem::update);
connect(this, &SpiralItem::resizeByVertexCountChanged,
this, &SpiralItem::handleResizeByVertexCountChanged);
emit resizeByVertexCountChanged();
}
QSGNode *SpiralItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) {
auto *n = static_cast<QSGGeometryNode *>(oldNode);
if (!n) {
n = new QSGGeometryNode();
setupGeometryNode(n);
}
if (auto *geometry = n->geometry()) {
if (m_vertexCount != geometry->vertexCount()) {
updateGeometry(geometry);
}
}
n->markDirty(QSGNode::DirtyGeometry);
return n;
}
void SpiralItem::updateGeometry(QSGGeometry *&geometry) {
if (m_resetVertices) {
m_resetVertices = false;
// must reallocate vertices if using setVertexCount to resize
if (m_resizeByVertexCount)
reallocateVertices(geometry, m_maxVertices);
}
const int newCount = qBound(0, m_vertexCount, m_maxVertices);
if (m_resizeByVertexCount) {
// change vertex count using new setVertexCount() function
geometry->setVertexCount(newCount);
} else {
// change vertex count using allocate()
reallocateVertices(geometry, newCount);
}
logStatistics();
}
void SpiralItem::setupGeometryNode(QSGGeometryNode *geometryNode)
{
// Set the geometry on the node
auto *geometry = createGeometry();
geometryNode->setGeometry(geometry);
geometryNode->setFlag(QSGNode::OwnsGeometry);
// Set a ColoredPoint2D material
geometryNode->setMaterial(new QSGVertexColorMaterial());
geometryNode->setFlag(QSGNode::OwnsMaterial);
}
QSGGeometry *SpiralItem::createGeometry()
{
auto *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(),
m_maxVertices);
geometry->setDrawingMode(QSGGeometry::DrawLineStrip);
geometry->setLineWidth(3);
// populate the geometry
populateVertices(geometry, m_maxVertices);
populateColors(geometry, m_maxVertices);
return geometry;
}
void SpiralItem::populateVertices(QSGGeometry *geometry, const int count)
{
constexpr double pi = 3.14159265f;
constexpr int linesPerRing = 720;
constexpr float angleIncrement = 2 * pi / linesPerRing;
constexpr float lineSeparation = 6;
constexpr float radiusIncrement = lineSeparation / linesPerRing;
float radius = 1.5f;
float xOffset = width()/2;
float yOffset = height()/2;
float angle = float(2 * pi / 1000.f);;
// Iterate through all vertices
auto *pt = geometry->vertexDataAsColoredPoint2D();
for (int i = 0; i < count; ++i, ++pt) {
pt->x = radius * cos(angle) + xOffset;
pt->y = radius * sin(angle) + yOffset;
radius += radiusIncrement;
// Keep angle in 2*pi radians -- makes debugging easier
angle += angleIncrement;
if (angle > 2 * M_PI)
angle = (2 * M_PI) - angle;
}
}
void SpiralItem::populateColors(QSGGeometry *geometry, const int count)
{
constexpr int segmentLength = 20;
const auto& colors = m_resizeByVertexCount ? setVCPalette : allocPalette;
auto *pt = geometry->vertexDataAsColoredPoint2D();
for (int i = 0; i < count; ++i, ++pt) {
const bool isEndOfSpiral = i <= 20*segmentLength
|| i > (m_maxVertices - segmentLength);
auto index = isEndOfSpiral ? 2 :
((i/segmentLength)%2 == 0) ? 1
: 0;
const auto [r, g, b, a] = getParts(colors[index]);
pt->r = r;
pt->g = g;
pt->b = b;
pt->a = a;
}
}
void SpiralItem::reallocateVertices(QSGGeometry *geometry, const int count) {
geometry->allocate(count);
populateVertices(geometry, count);
populateColors(geometry, count);
}
void SpiralItem::logStatistics()
{
if (!m_animating)
return;
if (m_vertexCount > m_maxCount)
m_maxCount = m_vertexCount;
if (m_vertexCount < m_minCount)
m_minCount = m_vertexCount;
if (m_statisticsTimer.elapsed() >= 1000) {
qDebug() << m_mode
<< "\tfps:" << m_fps
<< "\tvertices:" << m_minCount << "-" << m_maxCount;
m_statisticsTimer.restart();
m_maxCount = -1;
m_minCount = m_maxVertices;
}
}
int SpiralItem::vertexCount() const
{
return m_vertexCount;
}
void SpiralItem::setVertexCount(int newVertexCount)
{
if (m_vertexCount == newVertexCount)
return;
m_vertexCount = newVertexCount;
emit vertexCountChanged();
}
int SpiralItem::maxVertices() const
{
return m_maxVertices;
}
int SpiralItem::fps() const
{
return m_fps;
}
void SpiralItem::setFps(int newFps)
{
if (m_fps == newFps)
return;
m_fps = newFps;
emit fpsChanged();
}
void SpiralItem::toggleMode()
{
if (!m_animating) {
// Set up to alternate between techniques for resizing geometry
m_statisticsTimer.start();
m_animating = true;
}
// Toggle between using setVertexCount() and allocate() to resize geometry
setResizeByVertexCount(!m_resizeByVertexCount);
m_resetVertices = true;
}
void SpiralItem::handleResizeByVertexCountChanged()
{
setMode(m_resizeByVertexCount ? "setVertexCount()" : "allocate()");
}
QString SpiralItem::mode() const
{
return m_mode;
}
void SpiralItem::setMode(const QString &newMode)
{
if (m_mode == newMode)
return;
m_mode = newMode;
emit modeChanged();
}
bool SpiralItem::resizeByVertexCount() const
{
return m_resizeByVertexCount;
}
void SpiralItem::setResizeByVertexCount(bool newResizeByVertexCount)
{
if (m_resizeByVertexCount == newResizeByVertexCount)
return;
m_resizeByVertexCount = newResizeByVertexCount;
emit resizeByVertexCountChanged();
}
@@ -0,0 +1,70 @@
// Copyright (C) 2024 Stan Morris.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef SPIRALITEM_H
#define SPIRALITEM_H
#include <QQuickItem>
#include <QElapsedTimer>
class QSGGeometry;
class QSGGeometryNode;
class SpiralItem : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(int vertexCount READ vertexCount WRITE setVertexCount NOTIFY vertexCountChanged FINAL)
Q_PROPERTY(int maxVertices READ maxVertices CONSTANT FINAL)
Q_PROPERTY(int fps READ fps WRITE setFps NOTIFY fpsChanged FINAL)
Q_PROPERTY(QString mode READ mode WRITE setMode NOTIFY modeChanged FINAL)
Q_PROPERTY(bool resizeByVertexCount READ resizeByVertexCount NOTIFY resizeByVertexCountChanged FINAL)
QML_ELEMENT
public:
SpiralItem();
signals:
void vertexCountChanged();
void fpsChanged();
void cpuChanged();
void modeChanged();
void resizeByVertexCountChanged();
public slots:
void toggleMode();
void handleResizeByVertexCountChanged();
protected:
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
private:
void updateGeometry(QSGGeometry *&geometry);
void setupGeometryNode(QSGGeometryNode *);
QSGGeometry *createGeometry();
void populateVertices(QSGGeometry *, const int count);
void populateColors(QSGGeometry *, const int count);
void reallocateVertices(QSGGeometry* geometry, const int count);
void logStatistics();
int vertexCount() const;
void setVertexCount(int newVertexCount);
int maxVertices() const;
int fps() const;
void setFps(int newFps);
QString mode() const;
void setMode(const QString &newMode);
bool resizeByVertexCount() const;
void setResizeByVertexCount(bool newResizeByVertexCount);
QElapsedTimer m_statisticsTimer;
QString m_mode;
const int m_maxVertices {60000};
int m_vertexCount {0};
int m_fps = {};
bool m_resizeByVertexCount = {true};
bool m_animating = {false};
bool m_resetVertices = {false};
int m_maxCount {-1};
int m_minCount {m_maxVertices};
};
#endif // SPIRALITEM_H
@@ -0,0 +1,28 @@
// Copyright (C) 2024 Stan Morris
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
// Uncomment to show performance metrics
//qputenv("QSG_RENDERER_DEBUG", "render"); // Show number of batches
//qputenv("QSG_VISUALIZE", "batches"); // Show GPU batches
//qputenv("QSG_RENDER_TIMING", "1"); // Show GPU timings
//qputenv("QSG_VISUALIZE", "clip"); // Show Items with clip == true
//qputenv("QSG_VISUALIZE", "changes"); // Show updating items
//qputenv("QSG_VISUALIZE", "overdraw"); // Show off-screen Items, hidden Items
//qputenv("QSG_RENDER_LOOP", "threaded"); // types: basic, windows, threaded
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
&app, []() { QCoreApplication::exit(-1); },
Qt::QueuedConnection);
engine.loadFromModule("VertexSpiral", "Main");
return app.exec();
}