docs: add staged log capture and automated boot testing
This commit is contained in:
1 parent
40ad29e5a4
commit
dff0f533f7
20 files changed
+642
-78
No files matched your search
@@ -20,7 +20,7 @@ files in UniXNU before selecting components or changing a port:
|
||||
| Component work | Component page under `docs/drivers/`, component `README.md`, catalog build command, dependencies, and relevant source |
|
||||
| Kernel work | `docs/xnu/source-and-patches.md`, `docs/xnu/patch-reference.md`, selected OS `profile.toml`, XNU source and ordered patch series |
|
||||
| Image assembly | `docs/concepts/prelink.md`, `docs/concepts/payload.md`, `docs/porting/uefi-firmware.md`, device firmware configuration |
|
||||
| Verification | `docs/building.md`, `docs/porting/bring-up.md`, selected device page |
|
||||
| Verification | `docs/building.md`, `docs/porting/bring-up.md`, `docs/porting/log-capture.md`, selected device page |
|
||||
| Migration | `docs/porting/migration.md` |
|
||||
| Documentation | `docs/contributing/documentation.md` |
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ function taskSidebars(prefix: string, zh: boolean) {
|
||||
item('Boot the image', '启动镜像', 'guide/boot'),
|
||||
item('Boot arguments', '启动参数', 'xnu/boot-arguments'),
|
||||
item('Logs and checkpoints', '日志与检查点', 'guide/debugging'),
|
||||
item('Capture logs', '抓取日志', 'porting/log-capture'),
|
||||
item('Troubleshooting', '故障排查', 'reference/troubleshooting'),
|
||||
item('QEMU verification', 'QEMU 验证', 'reference/qemu'),
|
||||
]),
|
||||
@@ -55,6 +56,7 @@ function taskSidebars(prefix: string, zh: boolean) {
|
||||
group('4. Verify and publish', '4. 验证与发布', [
|
||||
item('Build and boot', '构建与启动', 'building'),
|
||||
item('Bring-up sequence', '启动验证顺序', 'porting/bring-up'),
|
||||
item('Log capture and boot tests', '日志抓取与启动测试', 'porting/log-capture'),
|
||||
item('Porting record', '适配记录', 'porting/records'),
|
||||
item('Publish documentation', '发布文档', 'contributing/documentation'),
|
||||
]),
|
||||
@@ -138,7 +140,7 @@ export default withMermaid(defineConfig({
|
||||
items: [
|
||||
{ text: '设备列表', link: '/zh/devices/' },
|
||||
{ text: '小米平板 6S Pro(sheng)', link: '/zh/devices/sheng' },
|
||||
{ text: '无人值守测试', link: '/zh/devices/sheng-unattended-test' },
|
||||
{ text: 'sheng 日志抓取示例', link: '/zh/devices/sheng-unattended-test' },
|
||||
{
|
||||
text: '社区移植',
|
||||
collapsed: true,
|
||||
@@ -253,7 +255,6 @@ export default withMermaid(defineConfig({
|
||||
alt: 'UniXNU',
|
||||
},
|
||||
siteTitle: 'UniXNU',
|
||||
socialLinks: [{ icon: 'github', link: 'https://github.com/UniXNU/UniXNU' }],
|
||||
nav: [
|
||||
{ text: 'Port a device', link: '/porting/', activeMatch: '^/porting/' },
|
||||
{ text: 'Build and boot', link: '/building', activeMatch: '^/(guide/|building)' },
|
||||
@@ -273,7 +274,7 @@ export default withMermaid(defineConfig({
|
||||
items: [
|
||||
{ text: 'Devices', link: '/devices/' },
|
||||
{ text: 'Xiaomi Pad 6S Pro (sheng)', link: '/devices/sheng' },
|
||||
{ text: 'Unattended test cycle', link: '/devices/sheng-unattended-test' },
|
||||
{ text: 'sheng log capture example', link: '/devices/sheng-unattended-test' },
|
||||
{
|
||||
text: 'Community ports',
|
||||
collapsed: true,
|
||||
|
||||
@@ -1,60 +1,152 @@
|
||||
# Unattended test cycle
|
||||
# sheng log capture example
|
||||
|
||||
Two boot arguments make a sheng hardware run unattended. Neither is enabled by default.
|
||||
Follow [Capture logs and automate boot tests](/porting/log-capture) for the porting
|
||||
sequence, including QR export during firmware bring-up. This page supplies sheng's
|
||||
storage, reset and reader inputs for the later capture stages.
|
||||
|
||||
| Argument | Effect |
|
||||
## 1. Prepare the inputs
|
||||
|
||||
Use the selected [sheng repository](/devices/sheng), a built kernel/package,
|
||||
configured [local build inputs](/reference/configuration#local-build-inputs),
|
||||
fastboot and Python 3. Run the following commands from the main UniXNU checkout:
|
||||
|
||||
```sh
|
||||
DEVICE_REPO=$(cd ../UniXNU-sheng && pwd)
|
||||
TARGET="$PWD/out/sheng/ipados-17.7.11-21H461/sheng"
|
||||
mkdir -p "$TARGET/boot"
|
||||
fastboot devices
|
||||
```
|
||||
|
||||
Record the device serial for the commands below. The reader needs these inputs:
|
||||
|
||||
- `boot_sheng_singleboot.img` from the
|
||||
[sheng Linux release](https://github.com/ianchb/sm8550-mainline/releases), with
|
||||
Android header version 0, appended DTB and an empty ramdisk.
|
||||
- A static AArch64 Linux BusyBox with shell, mount, USB-reader utilities,
|
||||
`dd`, `gzip`, `base64` and `md5sum` applets.
|
||||
- `nvmem-reboot-mode.ko` from the same kernel release's `linux-xiaomi-sheng.deb`.
|
||||
- `rebootbl`, compiled from `package/linux-log/rebootbl.cpp` with an AArch64 Linux
|
||||
toolchain. It uses Linux syscalls and the board DT's reboot-mode cell.
|
||||
|
||||
For example, with LLVM's `clang++` and `ld.lld` installed:
|
||||
|
||||
```sh
|
||||
clang++ --target=aarch64-linux-gnu -fuse-ld=lld -nostdlib -static \
|
||||
-fno-stack-protector -fno-exceptions -fno-rtti -Wl,-e,start \
|
||||
"$DEVICE_REPO/package/linux-log/rebootbl.cpp" -o "$TARGET/boot/rebootbl"
|
||||
python3 "$DEVICE_REPO/package/linux-log/build-linux-log-boot.py" \
|
||||
--boot /path/to/boot_sheng_singleboot.img --busybox /path/to/busybox \
|
||||
--rebootbl "$TARGET/boot/rebootbl" --module /path/to/nvmem-reboot-mode.ko \
|
||||
--out "$TARGET/boot/sheng-linux-log.img"
|
||||
```
|
||||
|
||||
**Result:** a reader image that uses sheng's Linux kernel and DTB. It reads the
|
||||
last 32 MiB of `userdata` into RAM and exposes a USB CDC ACM shell. Storage access
|
||||
is read-only. Its build command prints `BUILT` and the output path.
|
||||
|
||||
## 2. Build a logging image
|
||||
|
||||
`BootLog.c` writes diagnostic snapshots and the kernel message buffer through
|
||||
ShengUfs into the reserved last 32 MiB of `userdata`. The writer opens the region
|
||||
after ShengUfs reads the root layout. Check that this reservation matches the
|
||||
installed [storage layout](/concepts/userdata).
|
||||
|
||||
| Argument | Behavior |
|
||||
| --- | --- |
|
||||
| `sheng-log=1` | Starts `BootLog` from the board monitor. It writes the diagnostic page, banner, GPU rows and kernel message buffer to the last 32 MiB of `userdata`. |
|
||||
| `sheng-autoreset=<seconds>` | After that many seconds of log time, writes the PMIC reboot-reason cell and resets into fastboot. It runs only with `sheng-log=1`. |
|
||||
| `sheng-log=1` | Start the persistent writer from the board monitor |
|
||||
| `sheng-autoreset=120` | Attempt return to fastboot after 120 seconds of log time and a successful sync; the board monitor also marks the reboot reason and starts watchdog recovery when its hardware probe succeeds |
|
||||
|
||||
Build the test image with both arguments:
|
||||
Build a logging payload first, using the saved local inputs:
|
||||
|
||||
```sh
|
||||
./unixnu build payload --unique-chip-id <hex> --trust-cache <bundle> --data-ramdisk <seed> \
|
||||
--kernel-arg=sheng-log=1 --kernel-arg=sheng-autoreset=120
|
||||
./unixnu payload --kernel-arg=sheng-log=1
|
||||
./unixnu bootimg
|
||||
```
|
||||
|
||||
The log writer opens the window only after ShengUfs has read the root layout. The reset happens once, after that round's log is on the medium.
|
||||
**Result:** `payload/` and `boot/boot.img` under `$TARGET` contain the updated
|
||||
arguments. Complete the manual cycle before adding timed reset.
|
||||
|
||||
## Log reader
|
||||
## 3. Run one manual capture {#manual-cycle}
|
||||
|
||||
The reader is a fastboot-boot-only Linux image. It copies the log window into RAM, offers a USB CDC ACM shell and mounts nothing. Build it from the pinned Linux release inputs:
|
||||
Set `SERIAL` to the identifier reported by `fastboot devices`:
|
||||
|
||||
```sh
|
||||
python3 package/linux-log/build-linux-log-boot.py \
|
||||
--boot boot_sheng_singleboot.img --busybox busybox \
|
||||
--rebootbl rebootbl --module nvmem-reboot-mode.ko \
|
||||
--out out/sheng/ipados-17.7.11-21H461/sheng/boot/sheng-linux-log.img
|
||||
SERIAL=<serial>
|
||||
fastboot -s "$SERIAL" boot "$TARGET/boot/boot.img"
|
||||
```
|
||||
|
||||
`rebootbl` is the static aarch64 Linux program in `package/linux-log/rebootbl.cpp`. It calls `reboot(RESTART2, "bootloader")` through the device tree's `nvmem-reboot-mode` cell.
|
||||
|
||||
## Run
|
||||
Wait for the checkpoint under test, then use the device's bootloader key sequence
|
||||
to return to fastboot. Boot the reader:
|
||||
|
||||
```sh
|
||||
fastboot boot out/sheng/ipados-17.7.11-21H461/sheng/boot/boot.img
|
||||
# Wait for the tablet to return to fastboot by itself.
|
||||
fastboot boot out/sheng/ipados-17.7.11-21H461/sheng/boot/sheng-linux-log.img
|
||||
python3 scripts/read-sheng-log.py --wait 240
|
||||
fastboot -s "$SERIAL" boot "$TARGET/boot/sheng-linux-log.img"
|
||||
```
|
||||
|
||||
`read-sheng-log.py` fetches the window over `/dev/cu.usbmodem*`, writes `build/sheng-logs/<tag>-<boot id>/` and then runs `rebootbl`. The tablet returns to fastboot for the next image.
|
||||
|
||||
The one-command form runs the same cycle:
|
||||
Wait for its `ready: shell on USB serial` message. On macOS:
|
||||
|
||||
```sh
|
||||
SERIAL=<serial> READER=out/sheng/ipados-17.7.11-21H461/sheng/boot/sheng-linux-log.img \
|
||||
scripts/run-sheng-unattended.sh out/sheng/ipados-17.7.11-21H461/sheng/boot/boot.img 420
|
||||
python3 "$DEVICE_REPO/scripts/read-sheng-log.py" --wait 240 --out "$TARGET/logs/captures"
|
||||
```
|
||||
|
||||
If the tablet does not return within the limit, the script says so and waits for a manual fastboot entry.
|
||||
On Linux, find the reader's actual CDC port, ensure your account can open it,
|
||||
then pass it explicitly:
|
||||
|
||||
## Default off
|
||||
```sh
|
||||
ls /dev/ttyACM*
|
||||
python3 "$DEVICE_REPO/scripts/read-sheng-log.py" \
|
||||
--port /dev/ttyACM0 --out "$TARGET/logs/captures"
|
||||
```
|
||||
|
||||
- `board.toml` and the default kernel arguments do not set `sheng-log` or `sheng-autoreset`.
|
||||
- `BootLog.c` and `BootReset.c` are compiled into the kernel, but they do nothing without those arguments.
|
||||
- The build scripts do not add the arguments to any image.
|
||||
**Result:** `logs/captures/<tag>-<boot id>/` contains `log.bin`, `header.txt`,
|
||||
`msgbuf.txt`, `slots.txt` and `latest.txt`. Check the boot ID, snapshots and write
|
||||
errors. The reader sends `/bin/rebootbl` after transfer. Confirm the same serial
|
||||
returns with `fastboot devices`. A `no log header` error calls for checking writer
|
||||
startup and the reserved region before repeating the run.
|
||||
|
||||
## Offline check
|
||||
## 4. Enable the automatic cycle {#automated-cycle}
|
||||
|
||||
`package/linux-log/check-linux-log-qemu.py` boots the reader in QEMU virt with a GPT disk that holds a synthetic log window. It checks partition lookup, the copy, the transfer and the decoder. It does not cover USB, UFS or the XNU writer.
|
||||
Rebuild both outputs with timed reset:
|
||||
|
||||
```sh
|
||||
./unixnu payload --kernel-arg=sheng-log=1 --kernel-arg=sheng-autoreset=120
|
||||
./unixnu bootimg
|
||||
```
|
||||
|
||||
The normal reset follows a successful log sync. The board monitor's watchdog
|
||||
path can recover a stalled kernel: it requests a 60-second watchdog timeout and
|
||||
pings until 60 seconds beyond the configured reset deadline. Record whether the
|
||||
run returned normally or needed recovery.
|
||||
|
||||
On a macOS host with one reader serial device, run:
|
||||
|
||||
```sh
|
||||
SERIAL="$SERIAL" READER="$TARGET/boot/sheng-linux-log.img" \
|
||||
bash "$DEVICE_REPO/scripts/run-sheng-unattended.sh" "$TARGET/boot/boot.img" 420
|
||||
```
|
||||
|
||||
The runner changes into the device repository, so these image paths are absolute.
|
||||
It boots the test image, waits for return to fastboot, starts the Linux reader and
|
||||
fetches the logs. Its automatic serial discovery uses `/dev/cu.usbmodem*`; on
|
||||
Linux, use the explicit-port capture in step 3 after the timed return, or adapt
|
||||
the runner to pass that port. The runner saves captures under
|
||||
`UniXNU-sheng/build/sheng-logs/<tag>-<boot id>/`.
|
||||
|
||||
If the 420-second return timeout expires, the runner reports it and waits for
|
||||
manual bootloader entry. Preserve this outcome in the [porting record](/porting/records).
|
||||
Confirm the final return to fastboot before starting another run.
|
||||
|
||||
## Reader verification
|
||||
|
||||
The existing `package/linux-log/check-linux-log-qemu.py` exercises partition
|
||||
lookup, RAM copying, transfer and decoding with a synthetic GPT log region:
|
||||
|
||||
```sh
|
||||
python3 "$DEVICE_REPO/package/linux-log/check-linux-log-qemu.py" \
|
||||
--image "$TARGET/boot/sheng-linux-log.img" --kernel /path/to/qemu-virt-linux-Image \
|
||||
--work "$TARGET/logs/reader-qemu"
|
||||
```
|
||||
|
||||
Use an AArch64 QEMU `virt` Linux kernel with virtio block support and the matching
|
||||
host QEMU tools. Record this host check separately from board storage writes,
|
||||
USB transfer and reset observations. Continue with the
|
||||
[shared test procedure](/porting/log-capture#automated-cycle).
|
||||
@@ -9,6 +9,8 @@ porting record. Use the [record guide](/porting/records),
|
||||
[repository specification](/porting/device-repository) and
|
||||
[UFS guide](/porting/ufs) with the relevant section below.
|
||||
|
||||
For repeated hardware runs, use the [unattended test cycle](/devices/sheng-unattended-test) to collect logs and return to fastboot.
|
||||
Follow [log capture and boot tests](/porting/log-capture) in bring-up order.
|
||||
The [sheng example](/devices/sheng-unattended-test) gives the reader inputs,
|
||||
storage region and reset commands for this board.
|
||||
|
||||
<!--@include: ../.vitepress/records/sheng.md-->
|
||||
@@ -1,6 +1,6 @@
|
||||
# Debugging and logs
|
||||
|
||||
A bring-up produces four kinds of evidence: serial output, the on-screen diagnostic page, the panic screen and build reports. Collect them together.
|
||||
Collect firmware logs, kernel output, diagnostic screenshots and build reports for each bring-up checkpoint.
|
||||
|
||||
## Procedure {#procedure}
|
||||
|
||||
@@ -10,6 +10,12 @@ A bring-up produces four kinds of evidence: serial output, the on-screen diagnos
|
||||
4. Apply one diagnostic change. Rebuild the affected artifact; boot-argument changes require `./unixnu payload` and `./unixnu bootimg`. Repeat the failing operation and record the last confirmed checkpoint.
|
||||
5. Save an [evidence bundle](#evidence-bundle) and update the affected [porting record](/porting/records). A useful result identifies the failing stage, input versions and exact error.
|
||||
|
||||
## Capture by boot stage
|
||||
|
||||
Follow [log capture and automated tests](/porting/log-capture): QR export from
|
||||
the firmware menu, UART or screen diagnostics at kernel entry, then persistent
|
||||
logs and automated cycles after storage works.
|
||||
|
||||
## USB debug terminal
|
||||
|
||||
The host tools from the giulia port are available as `scripts/debug_terminal.py` and the Windows CMD launcher `scripts/debug-terminal.cmd`. They capture CDC logs, queue bounded diagnostic commands, export topic logs and decode GSC1 framebuffer packets. Python 3.10 or newer is required. Interactive editing and PTY keyboard input require Windows CMD; scripted capture works on Windows, Linux and macOS.
|
||||
@@ -62,6 +68,8 @@ The optional C-sender interoperability test needs `GIULIA_SCREEN_FIXTURE` pointi
|
||||
|
||||
| Source | Transport | Use |
|
||||
| --- | --- | --- |
|
||||
| [Firmware log export](/porting/log-capture#qr-logs) | OneSend QR frames | Current UEFI Advanced Logger buffer |
|
||||
| [Persistent logs](/porting/log-capture#persistent-logs) | Reserved storage and Linux reader | Kernel messages and diagnostic snapshots |
|
||||
| UEFI serial | UART | Firmware, UniXNU and DarwinBoot |
|
||||
| Kernel serial | UART selected by `serial=` | XNU console and panic output |
|
||||
| Diagnostic page | Framebuffer | Live state after the console stops |
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ hero:
|
||||
text: Port a device
|
||||
link: /porting/
|
||||
- theme: brand
|
||||
text: Devices
|
||||
text: Supported devices
|
||||
link: /devices/
|
||||
- theme: alt
|
||||
text: GitHub
|
||||
|
||||
@@ -43,6 +43,10 @@ Minimal test: an empty ramdisk. UniXNU falls back to its built-in configuration
|
||||
./unixnu bootimg --uefi /path/to/Mu-Silicium --dtb board.dtb --ramdisk none
|
||||
```
|
||||
|
||||
Before continuing, [scan the firmware log](/porting/log-capture#qr-logs) from
|
||||
**Tools → Advanced Logger**. Prepare the platform logger and plugin with the
|
||||
[integration steps](/porting/log-capture#firmware-setup).
|
||||
|
||||
## Stage 3: Payload
|
||||
|
||||
Goal: UniXNU reads `unixnu.toml` and the payload files.
|
||||
@@ -98,6 +102,10 @@ Checks:
|
||||
|
||||
A root match failure leaves the kernel without a root device. Check the UUID, the window offsets and the partition capacity.
|
||||
|
||||
Once storage works, [adapt persistent capture](/porting/log-capture#persistent-logs)
|
||||
with a kernel writer and Linux reader. Complete one manual retrieval before
|
||||
enabling timed reset and the automated cycle.
|
||||
|
||||
## Stage 7: Userland
|
||||
|
||||
Goal: `launchd` runs and the first user process reaches a visible state.
|
||||
|
||||
@@ -104,6 +104,9 @@ Follow [UEFI integration](/porting/uefi-firmware#required-integration) to includ
|
||||
UniXNU, DarwinBoot and payload filesystem support. For a Mu-Silicium initrd,
|
||||
include `UniXNURamDiskDxe`, DiskIoDxe and FAT support in the DSC and FDF.
|
||||
|
||||
Include the [firmware log exporter](/porting/log-capture#firmware-setup) so
|
||||
you can scan logs from the menu during initial bring-up.
|
||||
|
||||
**Result:** a buildable firmware configuration and two identified tree inputs:
|
||||
the board DTS for XNU's ADT, and the firmware DTB for boot-image assembly.
|
||||
|
||||
@@ -133,6 +136,10 @@ in [apply arguments](/xnu/boot-arguments#apply-arguments).
|
||||
failure, record the last completed checkpoint and use [debugging](/guide/debugging)
|
||||
and [troubleshooting](/reference/troubleshooting).
|
||||
|
||||
Set up [QR log export](/porting/log-capture#firmware-setup) during firmware integration
|
||||
and save the firmware log before kernel handoff. After storage verification, follow
|
||||
the same guide through persistent capture, a manual cycle and automated tests.
|
||||
|
||||
## 8. Publish the port
|
||||
|
||||
Validate the record from the main checkout:
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
# Capture logs and automate boot tests
|
||||
|
||||
Set up log capture as you bring up the board. Start with firmware logs, collect
|
||||
kernel evidence at handoff, then add persistent logs and automated reboot cycles.
|
||||
Use the [bring-up checkpoints](/porting/bring-up) to identify the stage being tested.
|
||||
|
||||
| Stage | Required support | Saved result |
|
||||
| --- | --- | --- |
|
||||
| UEFI menu | GOP display, menu input, Advanced Logger and QR plugin | Firmware `.log` file scanned from the screen |
|
||||
| XNU entry | UART or framebuffer diagnostics | Serial log or photograph of the last checkpoint/panic |
|
||||
| Storage | Reserved log region, kernel writer and Linux reader | Kernel message buffer and diagnostic snapshots |
|
||||
| Repeated tests | Working log retrieval and return to bootloader | One evidence directory per boot |
|
||||
|
||||
## 1. Include the firmware log exporter {#firmware-setup}
|
||||
|
||||
Prepare the firmware checkout using [UEFI integration](/porting/uefi-firmware).
|
||||
The shared exporter is
|
||||
`package/UniXNUPkg/Driver/AdvancedLogDxe/AdvancedLogDxe.inf` in UniXNU.
|
||||
It reads the Advanced Logger memory buffer while UEFI boot services are active.
|
||||
|
||||
1. In the firmware DSC `[Components]`, add:
|
||||
|
||||
```ini
|
||||
UniXNUPkg/Driver/AdvancedLogDxe/AdvancedLogDxe.inf
|
||||
```
|
||||
|
||||
In the FDF's DXE firmware volume, add:
|
||||
|
||||
```ini
|
||||
INF UniXNUPkg/Driver/AdvancedLogDxe/AdvancedLogDxe.inf
|
||||
```
|
||||
|
||||
2. Enable the platform's Advanced Logger producer and route the desired firmware
|
||||
debug output into it. The exporter dispatches after `gAdvancedLoggerProtocolGuid`
|
||||
is installed. Its INF also requires `AdvLoggerPkg`, `MsGraphicsPkg`,
|
||||
`AdvancedLoggerAccessLib` and `QrEncoderLib`.
|
||||
From the firmware checkout, find the library instances supplied by its Mu revision:
|
||||
|
||||
```sh
|
||||
find . -name '*AdvancedLogger*.inf' -o -name '*QrEncoder*.inf'
|
||||
```
|
||||
|
||||
Map the access and QR libraries in the DSC `[LibraryClasses]` and include their
|
||||
package roots in `board.toml` `[firmware] packages`. Initialize the submodules
|
||||
containing those packages if the search returns no files. Use the platform's
|
||||
Advanced Logger configuration for its buffer and debug-library mappings.
|
||||
|
||||
3. Set `gUniXNUPkgTokenSpaceGuid.PcdUniXNUDeviceModel` in the DSC `[PcdsFixedAtBuild]`
|
||||
to the board's ASCII name. The export filename uses this value.
|
||||
4. In the device's `board.toml`, add `tools = true` to its existing `[payload]`
|
||||
table. This adds **Tools** to the generated boot menu. A hand-authored
|
||||
`unixnu.toml` uses an [entry with `action = "tools"`](/reference/boot-configuration).
|
||||
5. From the main UniXNU checkout, with the device selected and
|
||||
[local inputs configured](/reference/configuration#local-build-inputs), run:
|
||||
|
||||
```sh
|
||||
./unixnu firmware
|
||||
./unixnu payload
|
||||
./unixnu bootimg
|
||||
```
|
||||
|
||||
**Result:** the rebuilt image contains the exporter, and **Tools → Advanced Logger**
|
||||
appears when the platform's logging protocol is available.
|
||||
|
||||
## 2. Scan the firmware log before kernel handoff {#qr-logs}
|
||||
|
||||
Prepare a second phone or camera device with [OneSend (扫传)](https://onesend.01mvp.com).
|
||||
The exporter sends a sequence of OneSend QR frames.
|
||||
|
||||
1. Boot the image from the main checkout:
|
||||
|
||||
```sh
|
||||
fastboot devices
|
||||
fastboot -s <serial> boot out/<device>/<os_profile>/<config>/boot/boot.img
|
||||
```
|
||||
|
||||
2. Stay in the UniXNU menu. Select **Tools**, then **Advanced Logger**.
|
||||
The plugin takes a snapshot of the current firmware log when opened.
|
||||
If a loader error returns you to the menu, open the plugin then to capture it
|
||||
before resetting the device.
|
||||
3. Open OneSend's receiving scanner, allow camera access and keep the complete QR
|
||||
square in view. Keep scanning as frames cycle until the receiver finishes.
|
||||
4. Use **Down / j** to slow rotation and **Up / k** to speed it up. The initial
|
||||
interval is one second; five speeds range from 5 seconds to 250 milliseconds.
|
||||
Boards that map volume buttons to Up/Down use those buttons. **Enter** or
|
||||
**Escape** returns to the menu; a board's power button works when mapped to Enter.
|
||||
5. Save the received `<model>-<date>-<time>.log` with the image revision and last
|
||||
completed checkpoint. The filename uses the firmware clock. Check the text for
|
||||
the failing operation before rebuilding.
|
||||
|
||||
**Result:** a readable firmware log captured while the menu remains accessible.
|
||||
XNU execution after `ExitBootServices` uses the capture methods in step 3.
|
||||
|
||||
| Symptom | Action |
|
||||
| --- | --- |
|
||||
| Tools is missing | Check `[payload] tools`, rebuild the payload and repack the boot image |
|
||||
| Advanced Logger is missing | Check the INF in DSC/FDF, its dependencies and the platform's logger protocol |
|
||||
| `Advanced Logger: no log` | Check the Advanced Logger producer, debug routing and buffer configuration |
|
||||
| Scanner progress stops | Reduce rotation speed and keep scanning the repeating sequence |
|
||||
| Firmware stops before the menu | Capture the platform UART or photograph its last visible output |
|
||||
|
||||
## 3. Capture the kernel handoff {#kernel-logs}
|
||||
|
||||
1. Save the firmware log from step 2, then start the kernel entry.
|
||||
2. Follow [debugging](/guide/debugging#procedure) to capture the board's UART or
|
||||
framebuffer output. For a green handoff bar, use the
|
||||
[entry-probe procedure](/guide/debugging#green-bar).
|
||||
3. Photograph the complete panic screen or checkpoint, including registers and
|
||||
the last text lines. Record the kernel arguments from the built payload.
|
||||
4. After changing arguments, run `./unixnu payload` and `./unixnu bootimg` again.
|
||||
Repeat the same boot and compare the last confirmed checkpoint.
|
||||
|
||||
**Result:** evidence for the kernel stage even while storage is being adapted.
|
||||
Continue with persistent capture after [storage verification](/porting/ufs).
|
||||
|
||||
## 4. Adapt persistent capture to the board {#persistent-logs}
|
||||
|
||||
The [sheng implementation](/devices/sheng-unattended-test) provides a working
|
||||
source layout to study. Complete these board interfaces before enabling writes:
|
||||
|
||||
1. Reserve a log region in the target's storage layout. Record its partition,
|
||||
offset, size and block units alongside the root and Data regions. Check that
|
||||
the image builder, partition provider, writer and reader use the same bounds.
|
||||
2. Connect the kernel writer to the storage driver's bounded read/write and sync
|
||||
operations. Include the kernel message buffer, diagnostic snapshots, boot ID
|
||||
and write status. Start it after the storage region can be opened.
|
||||
3. Build a Linux reader for the target board with its kernel, DTB, storage driver,
|
||||
USB device controller and CDC ACM support. Copy the reserved region into RAM,
|
||||
then expose a serial shell for retrieval. Keep the source partitions read-only.
|
||||
4. Adapt the host decoder to the writer's header and snapshot format. Select the
|
||||
serial device explicitly on hosts whose device names differ from the reader's
|
||||
discovery pattern.
|
||||
5. Implement return to the board's bootloader in both XNU and the Linux reader.
|
||||
Use the target's reboot-reason mechanism and reset interface. Verify watchdog
|
||||
handling separately if automatic recovery from a stalled kernel is required.
|
||||
|
||||
Review `package/BootLog.c`, `BootReset.c`, `BootResetCore.h`, `package/linux-log/`
|
||||
and `scripts/read-sheng-log.py` in `UniXNU-sheng`. Its PMIC addresses, watchdog
|
||||
calls, userdata reservation and Linux image inputs are board configuration that
|
||||
the new port must supply from its own hardware sources.
|
||||
|
||||
**Result:** a documented log region, matching writer/reader/decoder, and a tested
|
||||
route back to the bootloader. Record these in the device repository.
|
||||
|
||||
## 5. Complete one manual capture cycle {#manual-cycle}
|
||||
|
||||
Use the selected device's documented logging arguments and reader image.
|
||||
The [sheng example](/devices/sheng-unattended-test#manual-cycle) supplies concrete
|
||||
commands for that implementation.
|
||||
|
||||
1. Build a test payload with logging enabled, then rebuild its boot image.
|
||||
2. Run `fastboot -s <serial> boot <test.img>`. Wait for the log writer to run.
|
||||
3. Return to fastboot using the board's verified reset method. Run
|
||||
`fastboot -s <serial> boot <reader.img>`.
|
||||
4. Run the board's host reader. Save the raw window and decoded text under a
|
||||
directory identified by the boot ID. Confirm the header belongs to this boot,
|
||||
snapshots are present and write status is successful.
|
||||
5. Return to fastboot from the reader and confirm the same serial with
|
||||
`fastboot devices`.
|
||||
|
||||
**Result:** one complete test, saved logs and a device ready for the next image.
|
||||
If the header is missing or stale, check writer startup and region geometry.
|
||||
If the reader's serial port is absent, check its Linux USB gadget and host access.
|
||||
|
||||
## 6. Automate the verified cycle {#automated-cycle}
|
||||
|
||||
1. Enable the board's timed return to bootloader. Keep the timeout longer than
|
||||
the checkpoint being measured and allow time for log synchronization.
|
||||
2. Configure a host runner with the exact fastboot serial, absolute test-image
|
||||
path, absolute reader-image path and a timeout covering the boot and reset.
|
||||
3. Have it boot the test image, observe USB departure and return, boot the reader,
|
||||
retrieve logs, and confirm the final return to fastboot. Use the
|
||||
[sheng runner example](/devices/sheng-unattended-test#automated-cycle) when those
|
||||
board interfaces match.
|
||||
4. On timeout, record the failed stage and recover through the board's documented
|
||||
bootloader procedure. Keep this run's images and partial evidence.
|
||||
5. Repeat after one change. Record revisions, arguments, checkpoint, reset result,
|
||||
output directory and unresolved errors in the [porting record](/porting/records).
|
||||
|
||||
**Result:** each test produces an identifiable evidence directory and a recorded
|
||||
bootloader return. Continue the remaining [bring-up stages](/porting/bring-up).
|
||||
@@ -54,6 +54,13 @@ Build the payload with the selected device's inputs, then pack the image:
|
||||
|
||||
Use the options required by the device's payload profile. See [payload inputs](/concepts/payload).
|
||||
|
||||
## Firmware logs
|
||||
|
||||
Follow [log exporter integration](/porting/log-capture#firmware-setup) to add
|
||||
Advanced Logger and `AdvancedLogDxe`, then enable the Tools menu. Use
|
||||
[QR capture](/porting/log-capture#qr-logs) to save firmware output before storage
|
||||
adaptation and kernel handoff.
|
||||
|
||||
## Payload discovery
|
||||
|
||||
The Android bootloader places the FAT payload in RAM and writes `/chosen/linux,initrd-start` and `linux,initrd-end` into the firmware FDT. Each property is a 32-bit or 64-bit big-endian address. The range must contain complete 512-byte sectors and remain reserved while UEFI uses it.
|
||||
|
||||
@@ -163,6 +163,7 @@ Types are `s` for string, `x` for hex cells, `i` for decimal cells, `u` for unsi
|
||||
| `panic_screen` | boolean | Patch the panic screen into the payload kernel |
|
||||
| `trust_cache_sha256` | array | Accepted trust cache hashes. An owner bundle passed with `--owner-trust-cache` skips this list |
|
||||
| `kernel_args` | array | Default kernel arguments |
|
||||
| `tools` | boolean | Add Tools to the generated menu; configure plugins with [log capture](/porting/log-capture#firmware-setup) |
|
||||
| `timeout` | integer | Menu timeout |
|
||||
| `skip_setup_tool` | string | Script used by `--skip-setup` |
|
||||
|
||||
|
||||
@@ -1,60 +1,140 @@
|
||||
# 无人值守测试流程
|
||||
# sheng 日志抓取示例
|
||||
|
||||
两个启动参数让 sheng 的硬件测试无人值守。两者默认都不开启。
|
||||
按[抓取日志与自动启动测试](/zh/porting/log-capture)执行移植步骤,其中包含固件阶段的二维码导出。
|
||||
本页提供后续抓取阶段所需的 sheng 存储、复位和读取器输入。
|
||||
|
||||
| 参数 | 作用 |
|
||||
## 1. 准备输入
|
||||
|
||||
准备已选定的 [sheng 仓库](/zh/devices/sheng)、已构建的内核与 package、
|
||||
已填写的[本地构建输入](/zh/reference/configuration#local-build-inputs)、fastboot 和 Python 3。
|
||||
从 UniXNU 主仓库运行以下命令:
|
||||
|
||||
```sh
|
||||
DEVICE_REPO=$(cd ../UniXNU-sheng && pwd)
|
||||
TARGET="$PWD/out/sheng/ipados-17.7.11-21H461/sheng"
|
||||
mkdir -p "$TARGET/boot"
|
||||
fastboot devices
|
||||
```
|
||||
|
||||
记录设备序列号,用于后续命令。读取器需要以下输入:
|
||||
|
||||
- [sheng Linux release](https://github.com/ianchb/sm8550-mainline/releases) 中的
|
||||
`boot_sheng_singleboot.img`,包含 Android header v0、追加的 DTB 和空 ramdisk。
|
||||
- 静态链接的 AArch64 Linux BusyBox,包含 shell、mount、USB 读取器所需工具,
|
||||
以及 `dd`、`gzip`、`base64` 和 `md5sum` applet。
|
||||
- 同一内核 release 的 `linux-xiaomi-sheng.deb` 中的 `nvmem-reboot-mode.ko`。
|
||||
- 用 AArch64 Linux 工具链从 `package/linux-log/rebootbl.cpp` 编译的 `rebootbl`。
|
||||
它使用 Linux 系统调用和板型 DT 的 reboot-mode cell。
|
||||
|
||||
例如,安装 LLVM 的 `clang++` 和 `ld.lld` 后:
|
||||
|
||||
```sh
|
||||
clang++ --target=aarch64-linux-gnu -fuse-ld=lld -nostdlib -static \
|
||||
-fno-stack-protector -fno-exceptions -fno-rtti -Wl,-e,start \
|
||||
"$DEVICE_REPO/package/linux-log/rebootbl.cpp" -o "$TARGET/boot/rebootbl"
|
||||
python3 "$DEVICE_REPO/package/linux-log/build-linux-log-boot.py" \
|
||||
--boot /path/to/boot_sheng_singleboot.img --busybox /path/to/busybox \
|
||||
--rebootbl "$TARGET/boot/rebootbl" --module /path/to/nvmem-reboot-mode.ko \
|
||||
--out "$TARGET/boot/sheng-linux-log.img"
|
||||
```
|
||||
|
||||
**结果:** 生成使用 sheng Linux 内核和 DTB 的读取器镜像。它将 `userdata` 最后 32 MiB
|
||||
复制到 RAM,提供 USB CDC ACM shell,存储访问保持只读。构建命令打印 `BUILT` 和输出路径。
|
||||
|
||||
## 2. 构建日志镜像
|
||||
|
||||
`BootLog.c` 通过 ShengUfs 将诊断快照和内核消息缓冲写入 `userdata` 末尾预留的 32 MiB。
|
||||
ShengUfs 读取根布局后,写入器才能打开该区域。先确认预留区域与已安装的[存储布局](/zh/concepts/userdata)一致。
|
||||
|
||||
| 参数 | 行为 |
|
||||
| --- | --- |
|
||||
| `sheng-log=1` | 从板级监控启动 `BootLog`,把诊断页、banner、GPU 行和内核消息缓冲写入 `userdata` 最后 32 MiB。 |
|
||||
| `sheng-autoreset=<秒>` | 日志时间达到该秒数后,写入 PMIC reboot-reason cell 并重启到 fastboot。只在 `sheng-log=1` 时运行。 |
|
||||
| `sheng-log=1` | 从板级监控启动持久化写入器 |
|
||||
| `sheng-autoreset=120` | 日志时间达到 120 秒且同步成功后尝试返回 fastboot;硬件探测成功时,板级监控还会设置重启原因并启动 watchdog 恢复 |
|
||||
|
||||
构建同时带两个参数的测试镜像:
|
||||
先使用已保存的本地输入构建日志 payload:
|
||||
|
||||
```sh
|
||||
./unixnu build payload --unique-chip-id <hex> --trust-cache <bundle> --data-ramdisk <seed> \
|
||||
--kernel-arg=sheng-log=1 --kernel-arg=sheng-autoreset=120
|
||||
./unixnu payload --kernel-arg=sheng-log=1
|
||||
./unixnu bootimg
|
||||
```
|
||||
|
||||
日志写入器在 ShengUfs 读取根布局后才打开窗口。reset 只执行一次,且在该轮日志落盘之后。
|
||||
**结果:** `$TARGET` 下的 `payload/` 和 `boot/boot.img` 包含更新后的参数。
|
||||
完成手动抓取后再加入定时复位。
|
||||
|
||||
## 日志读取器
|
||||
## 3. 手动抓取一次 {#manual-cycle}
|
||||
|
||||
读取器是只通过 fastboot 启动的 Linux 镜像。它把日志窗口复制到 RAM,提供 USB CDC ACM shell,不挂载任何分区。用固定的 Linux release 输入构建:
|
||||
将 `SERIAL` 设置为 `fastboot devices` 显示的标识:
|
||||
|
||||
```sh
|
||||
python3 package/linux-log/build-linux-log-boot.py \
|
||||
--boot boot_sheng_singleboot.img --busybox busybox \
|
||||
--rebootbl rebootbl --module nvmem-reboot-mode.ko \
|
||||
--out out/sheng/ipados-17.7.11-21H461/sheng/boot/sheng-linux-log.img
|
||||
SERIAL=<serial>
|
||||
fastboot -s "$SERIAL" boot "$TARGET/boot/boot.img"
|
||||
```
|
||||
|
||||
`rebootbl` 是 `package/linux-log/rebootbl.cpp` 中的静态 aarch64 Linux 程序。它通过设备树的 `nvmem-reboot-mode` cell 调用 `reboot(RESTART2, "bootloader")`。
|
||||
|
||||
## 运行
|
||||
等待所测检查点,再使用设备的 bootloader 按键组合返回 fastboot。启动读取器:
|
||||
|
||||
```sh
|
||||
fastboot boot out/sheng/ipados-17.7.11-21H461/sheng/boot/boot.img
|
||||
# 等待平板自行回到 fastboot。
|
||||
fastboot boot out/sheng/ipados-17.7.11-21H461/sheng/boot/sheng-linux-log.img
|
||||
python3 scripts/read-sheng-log.py --wait 240
|
||||
fastboot -s "$SERIAL" boot "$TARGET/boot/sheng-linux-log.img"
|
||||
```
|
||||
|
||||
`read-sheng-log.py` 通过 `/dev/cu.usbmodem*` 取回窗口,写入 `build/sheng-logs/<tag>-<boot id>/`,然后运行 `rebootbl`。平板回到 fastboot,可以启动下一个镜像。
|
||||
|
||||
一条命令跑完整轮:
|
||||
等待显示 `ready: shell on USB serial`。macOS 上运行:
|
||||
|
||||
```sh
|
||||
SERIAL=<serial> READER=out/sheng/ipados-17.7.11-21H461/sheng/boot/sheng-linux-log.img \
|
||||
scripts/run-sheng-unattended.sh out/sheng/ipados-17.7.11-21H461/sheng/boot/boot.img 420
|
||||
python3 "$DEVICE_REPO/scripts/read-sheng-log.py" --wait 240 --out "$TARGET/logs/captures"
|
||||
```
|
||||
|
||||
如果平板没有在时限内返回,脚本会提示并等待手动进入 fastboot。
|
||||
Linux 上找到读取器的实际 CDC 端口,确认当前账号有访问权限,再显式指定:
|
||||
|
||||
## 默认关闭
|
||||
```sh
|
||||
ls /dev/ttyACM*
|
||||
python3 "$DEVICE_REPO/scripts/read-sheng-log.py" \
|
||||
--port /dev/ttyACM0 --out "$TARGET/logs/captures"
|
||||
```
|
||||
|
||||
- `board.toml` 和默认内核参数不设置 `sheng-log` 或 `sheng-autoreset`。
|
||||
- `BootLog.c` 和 `BootReset.c` 会编译进内核,但没有上述参数时不执行。
|
||||
- 构建脚本不会把参数加入任何镜像。
|
||||
**结果:** `logs/captures/<tag>-<boot id>/` 包含 `log.bin`、`header.txt`、`msgbuf.txt`、
|
||||
`slots.txt` 和 `latest.txt`。检查启动 ID、快照和写入错误。
|
||||
传输结束后读取器发送 `/bin/rebootbl`,用 `fastboot devices` 确认同一序列号返回。
|
||||
出现 `no log header` 时,先检查写入器是否启动、预留区域是否正确,再重复测试。
|
||||
|
||||
## 离线检查
|
||||
## 4. 启用自动循环 {#automated-cycle}
|
||||
|
||||
`package/linux-log/check-linux-log-qemu.py` 在 QEMU virt 中启动读取器,使用带合成日志窗口的 GPT 磁盘,检查分区查找、复制、传输和解码。它不覆盖 USB、UFS 或 XNU 写入器。
|
||||
加入定时复位后,重新构建两项输出:
|
||||
|
||||
```sh
|
||||
./unixnu payload --kernel-arg=sheng-log=1 --kernel-arg=sheng-autoreset=120
|
||||
./unixnu bootimg
|
||||
```
|
||||
|
||||
正常复位在日志同步成功后执行。板级监控的 watchdog 路径可恢复停滞的内核:
|
||||
它请求 60 秒 watchdog 超时,持续喂狗到配置的复位时限后 60 秒。
|
||||
记录本次属于正常返回还是超时恢复。
|
||||
|
||||
macOS 主机连接一个读取器串口时运行:
|
||||
|
||||
```sh
|
||||
SERIAL="$SERIAL" READER="$TARGET/boot/sheng-linux-log.img" \
|
||||
bash "$DEVICE_REPO/scripts/run-sheng-unattended.sh" "$TARGET/boot/boot.img" 420
|
||||
```
|
||||
|
||||
脚本会切换到设备仓库,因此这里使用镜像绝对路径。
|
||||
它启动测试镜像,等待返回 fastboot,启动 Linux 读取器并取回日志。
|
||||
自动串口发现使用 `/dev/cu.usbmodem*`;Linux 上可在定时返回后按步骤 3 显式指定端口,
|
||||
或为执行脚本加入端口传参。自动脚本将日志保存到
|
||||
`UniXNU-sheng/build/sheng-logs/<tag>-<boot id>/`。
|
||||
|
||||
超过 420 秒仍未返回时,脚本会报告超时并等待手动进入 bootloader。
|
||||
将该结果写入[适配记录](/zh/porting/records)。下一次测试前确认最终已回到 fastboot。
|
||||
|
||||
## 读取器验证
|
||||
|
||||
现有 `package/linux-log/check-linux-log-qemu.py` 使用合成 GPT 日志区域,
|
||||
检查分区查找、复制到 RAM、传输和解码:
|
||||
|
||||
```sh
|
||||
python3 "$DEVICE_REPO/package/linux-log/check-linux-log-qemu.py" \
|
||||
--image "$TARGET/boot/sheng-linux-log.img" --kernel /path/to/qemu-virt-linux-Image \
|
||||
--work "$TARGET/logs/reader-qemu"
|
||||
```
|
||||
|
||||
使用支持 virtio block 的 AArch64 QEMU `virt` Linux 内核,并安装相应主机 QEMU 工具。
|
||||
将这项主机检查与板级存储写入、USB 传输和复位观察分别记录。
|
||||
继续按[通用测试步骤](/zh/porting/log-capture#automated-cycle)操作。
|
||||
@@ -8,6 +8,7 @@
|
||||
[记录指南](/zh/porting/records)、[仓库规范](/zh/porting/device-repository)和
|
||||
[UFS 指南](/zh/porting/ufs)阅读下方对应部分。
|
||||
|
||||
重复实机验证可使用[无人值守测试流程](/zh/devices/sheng-unattended-test)采集日志并返回 fastboot。
|
||||
按移植顺序完成[日志抓取与启动测试](/zh/porting/log-capture)。
|
||||
[sheng 示例](/zh/devices/sheng-unattended-test)提供本板型的读取器输入、存储区域和复位命令。
|
||||
|
||||
<!--@include: ../../.vitepress/records/sheng.zh.md-->
|
||||
@@ -1,6 +1,6 @@
|
||||
# 调试与日志
|
||||
|
||||
bring-up 需要四类证据:串口输出、屏幕诊断页、panic 屏幕和构建报告。把它们一起收集。
|
||||
为每个启动检查点收集固件日志、内核输出、诊断截图和构建报告。
|
||||
|
||||
## 操作步骤 {#procedure}
|
||||
|
||||
@@ -10,6 +10,11 @@ bring-up 需要四类证据:串口输出、屏幕诊断页、panic 屏幕和
|
||||
4. 每次应用一项诊断修改,重新构建受影响的产物。启动参数修改需要 `./unixnu payload` 和 `./unixnu bootimg`。重复失败操作,记录最后确认的检查点。
|
||||
5. 保存[证据包](#证据包),更新对应[适配记录](/zh/porting/records)。结果应明确失败阶段、输入版本和具体错误。
|
||||
|
||||
## 按阶段抓取日志
|
||||
|
||||
按[日志抓取与自动测试步骤](/zh/porting/log-capture)操作:固件菜单中使用二维码导出,
|
||||
内核入口使用 UART 或屏幕诊断,存储完成后加入持久化日志和自动循环。
|
||||
|
||||
## USB 调试终端
|
||||
|
||||
来自 giulia 移植的电脑端工具已整合为 `scripts/debug_terminal.py` 和 Windows CMD 启动器 `scripts/debug-terminal.cmd`,支持 CDC 日志采集、有界诊断命令、按主题导出日志及 GSC1 帧缓冲解码。需要 Python 3.10 或更新版本。交互编辑与 PTY 键盘输入需要 Windows CMD;脚本采集可在 Windows、Linux 和 macOS 上运行。
|
||||
@@ -62,6 +67,8 @@ python -m unittest discover -s tests/terminal -v
|
||||
|
||||
| 来源 | 通道 | 用途 |
|
||||
| --- | --- | --- |
|
||||
| [固件日志导出](/zh/porting/log-capture#qr-logs) | OneSend 二维码 | 当前 UEFI Advanced Logger 缓冲 |
|
||||
| [持久化日志](/zh/porting/log-capture#persistent-logs) | 预留存储区域和 Linux 读取器 | 内核消息与诊断快照 |
|
||||
| UEFI 串口 | UART | 固件、UniXNU、DarwinBoot |
|
||||
| 内核串口 | 由 `serial=` 选择的 UART | XNU 控制台和 panic 输出 |
|
||||
| 诊断页 | framebuffer | 控制台停止后的实时状态 |
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ hero:
|
||||
text: 移植设备
|
||||
link: /zh/porting/
|
||||
- theme: brand
|
||||
text: 设备
|
||||
text: 已支持的设备
|
||||
link: /zh/devices/
|
||||
- theme: alt
|
||||
text: GitHub
|
||||
|
||||
@@ -41,6 +41,9 @@ fastboot boot out/<device>/<os_profile>/<config>/boot/boot.img
|
||||
./unixnu bootimg --uefi /path/to/Mu-Silicium --dtb board.dtb --ramdisk none
|
||||
```
|
||||
|
||||
继续前,按[二维码抓取步骤](/zh/porting/log-capture#qr-logs)从 **Tools → Advanced Logger**
|
||||
导出当前固件日志。先按[集成步骤](/zh/porting/log-capture#firmware-setup)准备平台日志模块和插件。
|
||||
|
||||
## 阶段 3:负载
|
||||
|
||||
目标:UniXNU 读取 `unixnu.toml` 和负载文件。
|
||||
@@ -96,6 +99,9 @@ fastboot boot out/<device>/<os_profile>/<config>/boot/boot.img
|
||||
|
||||
根卷匹配失败时内核没有根设备。检查 UUID、窗口偏移和分区容量。
|
||||
|
||||
存储可用后,按[持久化日志步骤](/zh/porting/log-capture#persistent-logs)接入写入器和 Linux 读取器,
|
||||
先手动取回一次日志,再启用定时重启和自动循环。
|
||||
|
||||
## 阶段 7:用户态
|
||||
|
||||
目标:`launchd` 运行,首个用户进程到达可见状态。
|
||||
|
||||
@@ -88,6 +88,9 @@ boot image 另需设备固件使用的 DTB。
|
||||
和 payload 文件系统支持。Mu-Silicium initrd 需要在 DSC 与 FDF 中加入
|
||||
`UniXNURamDiskDxe`、DiskIoDxe 和 FAT 支持。
|
||||
|
||||
按[固件日志导出器步骤](/zh/porting/log-capture#firmware-setup)加入插件,
|
||||
便于首次启动时从菜单扫描日志。
|
||||
|
||||
**结果:** 可构建的固件配置,以及用途明确的两个树输入:生成 XNU ADT 的板级 DTS、组装启动镜像的固件 DTB。
|
||||
|
||||
## 6. 按依赖顺序适配驱动
|
||||
@@ -112,6 +115,9 @@ Wi-Fi,再处理 DSP、音频和电源。每篇指南列出源码位置、板
|
||||
**结果:** 构建输出,以及单独记录的设备观测。失败时记录最后完成的阶段,继续
|
||||
[调试](/zh/guide/debugging)和[故障排查](/zh/reference/troubleshooting)。
|
||||
|
||||
在固件阶段先按[日志抓取步骤](/zh/porting/log-capture#firmware-setup)集成二维码导出,
|
||||
在内核交接前保存固件日志。存储验证完成后,继续该页的持久化抓取、手动循环和自动测试步骤。
|
||||
|
||||
## 8. 发布移植
|
||||
|
||||
从主仓库验证记录:
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
# 抓取日志与自动启动测试
|
||||
|
||||
按移植进度建立日志抓取流程:先获取固件日志,再记录内核交接,随后实现持久化日志和自动重启测试。
|
||||
使用[启动检查点](/zh/porting/bring-up)确定当前验证的阶段。
|
||||
|
||||
| 阶段 | 所需支持 | 保存结果 |
|
||||
| --- | --- | --- |
|
||||
| UEFI 菜单 | GOP 显示、菜单输入、Advanced Logger 和二维码插件 | 扫描屏幕导出的固件 `.log` 文件 |
|
||||
| XNU 入口 | UART 或屏幕诊断 | 串口日志或最后检查点/panic 的照片 |
|
||||
| 存储 | 预留日志区域、内核写入器和 Linux 读取器 | 内核消息缓冲和诊断快照 |
|
||||
| 重复测试 | 可用的日志读取与返回 bootloader 功能 | 每次启动独立的证据目录 |
|
||||
|
||||
## 1. 集成固件日志导出器 {#firmware-setup}
|
||||
|
||||
按 [UEFI 集成](/zh/porting/uefi-firmware)准备固件仓库。
|
||||
通用导出器位于 UniXNU 的
|
||||
`package/UniXNUPkg/Driver/AdvancedLogDxe/AdvancedLogDxe.inf`。
|
||||
它在 UEFI boot services 可用时读取 Advanced Logger 内存缓冲。
|
||||
|
||||
1. 在固件 DSC 的 `[Components]` 中加入:
|
||||
|
||||
```ini
|
||||
UniXNUPkg/Driver/AdvancedLogDxe/AdvancedLogDxe.inf
|
||||
```
|
||||
|
||||
在 FDF 的 DXE 固件卷中加入:
|
||||
|
||||
```ini
|
||||
INF UniXNUPkg/Driver/AdvancedLogDxe/AdvancedLogDxe.inf
|
||||
```
|
||||
|
||||
2. 启用平台的 Advanced Logger 日志收集模块,将所需固件调试输出接入它。
|
||||
导出器在 `gAdvancedLoggerProtocolGuid` 安装后加载。
|
||||
INF 还依赖 `AdvLoggerPkg`、`MsGraphicsPkg`、`AdvancedLoggerAccessLib` 和 `QrEncoderLib`。
|
||||
从固件仓库查找当前 Mu 版本提供的库实例:
|
||||
|
||||
```sh
|
||||
find . -name '*AdvancedLogger*.inf' -o -name '*QrEncoder*.inf'
|
||||
```
|
||||
|
||||
在 DSC `[LibraryClasses]` 中映射日志访问库和二维码库,将对应包根目录加入
|
||||
`board.toml` 的 `[firmware] packages`。查不到文件时先初始化这些包所在的子模块。
|
||||
日志缓冲区和调试库映射采用该平台的 Advanced Logger 配置。
|
||||
3. 在 DSC `[PcdsFixedAtBuild]` 中把 `gUniXNUPkgTokenSpaceGuid.PcdUniXNUDeviceModel`
|
||||
设置为板型的 ASCII 名称。导出文件名使用该值。
|
||||
4. 在设备 `board.toml` 已有的 `[payload]` 表中加入 `tools = true`,生成的启动菜单会包含
|
||||
**Tools**。手写的 `unixnu.toml` 使用 [`action = "tools"` 菜单项](/zh/reference/boot-configuration)。
|
||||
5. 从 UniXNU 主仓库运行以下命令。先选定设备,并填好[本地输入](/zh/reference/configuration#local-build-inputs):
|
||||
|
||||
```sh
|
||||
./unixnu firmware
|
||||
./unixnu payload
|
||||
./unixnu bootimg
|
||||
```
|
||||
|
||||
**结果:** 镜像包含导出器;平台日志协议可用时,菜单出现 **Tools → Advanced Logger**。
|
||||
|
||||
## 2. 在内核交接前扫描固件日志 {#qr-logs}
|
||||
|
||||
准备另一台带摄像头的手机或设备,打开 [OneSend(扫传)](https://onesend.01mvp.com)。
|
||||
导出器通过连续的 OneSend 二维码帧传输日志。
|
||||
|
||||
1. 从主仓库启动镜像:
|
||||
|
||||
```sh
|
||||
fastboot devices
|
||||
fastboot -s <serial> boot out/<device>/<os_profile>/<config>/boot/boot.img
|
||||
```
|
||||
|
||||
2. 停留在 UniXNU 菜单,选择 **Tools**,再选择 **Advanced Logger**。
|
||||
插件打开时读取一份当前固件日志快照。加载器报错并返回菜单时,在复位前打开插件抓取该错误。
|
||||
3. 打开扫传的接收扫描功能,允许使用摄像头,将完整二维码置于画面内。
|
||||
保持扫描轮播帧,直到接收端完成传输。
|
||||
4. **下键 / j** 降低轮播速度,**上键 / k** 提高速度。默认每秒一帧,五档间隔从 5 秒到
|
||||
250 毫秒。音量键映射为上下键的板型可使用音量键。按 **Enter** 或 **Escape** 返回菜单;
|
||||
电源键映射为 Enter 时也可用于返回。
|
||||
5. 保存收到的 `<model>-<date>-<time>.log`,附上镜像版本和最后完成的检查点。
|
||||
文件名使用固件时钟。重新构建前,先查看文件中失败操作的输出。
|
||||
|
||||
**结果:** 在菜单可操作时获得可读的固件日志。`ExitBootServices` 之后的 XNU 执行使用步骤 3 的抓取方式。
|
||||
|
||||
| 现象 | 操作 |
|
||||
| --- | --- |
|
||||
| 没有 Tools | 检查 `[payload] tools`,重建 payload 和启动镜像 |
|
||||
| 没有 Advanced Logger | 检查 DSC/FDF 中的 INF、依赖和平台日志协议 |
|
||||
| 显示 `Advanced Logger: no log` | 检查日志收集模块、调试输出接入和缓冲区配置 |
|
||||
| 扫描进度停止 | 降低轮播速度,继续扫描循环播放的帧 |
|
||||
| 固件在菜单前停止 | 抓取平台 UART,或拍摄最后可见输出 |
|
||||
|
||||
## 3. 记录内核交接 {#kernel-logs}
|
||||
|
||||
1. 保存步骤 2 的固件日志,再选择内核启动项。
|
||||
2. 按[调试步骤](/zh/guide/debugging#procedure)抓取板型 UART 或屏幕输出。
|
||||
停在绿色交接条时,按[入口探针步骤](/zh/guide/debugging#green-bar)操作。
|
||||
3. 拍摄完整 panic 屏幕或检查点,保留寄存器和最后几行文字。记录构建后 payload 中的内核参数。
|
||||
4. 修改参数后,重新运行 `./unixnu payload` 和 `./unixnu bootimg`。
|
||||
重复同一启动操作,对比最后确认的检查点。
|
||||
|
||||
**结果:** 存储适配期间也能保留内核阶段的证据。完成[存储验证](/zh/porting/ufs)后继续实现持久化抓取。
|
||||
|
||||
## 4. 为板型适配持久化抓取 {#persistent-logs}
|
||||
|
||||
参考 [sheng 实现](/zh/devices/sheng-unattended-test)的源码结构。
|
||||
启用写入前完成以下板级接口:
|
||||
|
||||
1. 在目标存储布局中预留日志区域,记录分区、偏移、大小和块单位,并与根卷及 Data 区域一起检查。
|
||||
镜像构建器、分区提供者、写入器和读取器必须使用相同边界。
|
||||
2. 将内核写入器接入存储驱动限定范围的读写与同步操作,记录内核消息缓冲、诊断快照、启动 ID 和写入状态。
|
||||
存储区域可打开后再启动写入器。
|
||||
3. 用目标板型的内核、DTB、存储驱动、USB 设备控制器和 CDC ACM 支持构建 Linux 读取器。
|
||||
将预留区域复制到 RAM,再提供串口 shell 供主机取回。源分区保持只读。
|
||||
4. 根据写入器的文件头和快照格式适配主机解码器。主机串口命名与自动发现规则不同时,显式指定端口。
|
||||
5. 在 XNU 和 Linux 读取器中实现返回板型 bootloader 的操作,采用目标硬件的重启原因机制和复位接口。
|
||||
需要内核停滞后自动恢复时,单独验证 watchdog。
|
||||
|
||||
阅读 `UniXNU-sheng` 中的 `package/BootLog.c`、`BootReset.c`、`BootResetCore.h`、
|
||||
`package/linux-log/` 和 `scripts/read-sheng-log.py`。
|
||||
其中 PMIC 地址、watchdog 调用、userdata 预留区域和 Linux 镜像输入需要按新板型的硬件资料填写。
|
||||
|
||||
**结果:** 日志区域有明确记录,写入器、读取器和解码器格式一致,返回 bootloader 的路径已验证。
|
||||
将这些信息写入设备仓库。
|
||||
|
||||
## 5. 手动完成一次抓取 {#manual-cycle}
|
||||
|
||||
使用选定设备文档中的日志参数和读取器镜像。
|
||||
[sheng 示例](/zh/devices/sheng-unattended-test#manual-cycle)提供该实现的完整命令。
|
||||
|
||||
1. 启用日志参数,构建测试 payload,再构建启动镜像。
|
||||
2. 运行 `fastboot -s <serial> boot <test.img>`,等待日志写入器运行。
|
||||
3. 使用板型已验证的复位方式返回 fastboot,运行 `fastboot -s <serial> boot <reader.img>`。
|
||||
4. 运行板型的主机读取器,将原始区域和解码文本存入按启动 ID 标识的目录。
|
||||
确认文件头属于本次启动,存在诊断快照,写入状态成功。
|
||||
5. 从读取器返回 fastboot,用 `fastboot devices` 确认同一序列号重新出现。
|
||||
|
||||
**结果:** 一次测试完成,日志已保存,设备可以启动下一份镜像。
|
||||
文件头缺失或属于旧启动时,检查写入器启动情况和区域范围。
|
||||
读取器串口未出现时,检查 Linux USB gadget 和主机访问权限。
|
||||
|
||||
## 6. 自动执行已验证的循环 {#automated-cycle}
|
||||
|
||||
1. 启用板型定时返回 bootloader 的功能。超时应长于所测检查点所需时间,并留出日志同步时间。
|
||||
2. 为主机执行脚本配置准确的 fastboot 序列号、测试镜像绝对路径、读取器镜像绝对路径,
|
||||
以及覆盖启动和复位所需时间的超时。
|
||||
3. 脚本依次启动测试镜像、观察 USB 断开和返回、启动读取器、抓取日志,并确认最后回到 fastboot。
|
||||
板级接口匹配时,可使用 [sheng 脚本示例](/zh/devices/sheng-unattended-test#automated-cycle)。
|
||||
4. 超时后记录失败阶段,按板型文档恢复到 bootloader。保留本次镜像和已获得的证据。
|
||||
5. 每次修改一项内容后重复测试。在[适配记录](/zh/porting/records)中填写版本、参数、检查点、复位结果、
|
||||
输出目录和未解决错误。
|
||||
|
||||
**结果:** 每次测试都有可识别的证据目录和返回 bootloader 的记录。继续完成其余[启动验证阶段](/zh/porting/bring-up)。
|
||||
@@ -54,6 +54,12 @@ FdtLib|MdePkg/Library/BaseFdtLib/BaseFdtLib.inf
|
||||
|
||||
按设备负载配置提供所需选项,详见[负载输入](/zh/concepts/payload)。
|
||||
|
||||
## 固件日志
|
||||
|
||||
按[日志导出器集成步骤](/zh/porting/log-capture#firmware-setup)加入 Advanced Logger 和
|
||||
`AdvancedLogDxe`,启用 Tools 菜单。在存储适配前,使用[二维码抓取](/zh/porting/log-capture#qr-logs)
|
||||
保存固件输出,再继续内核交接。
|
||||
|
||||
## 负载发现 {#payload-discovery}
|
||||
|
||||
Android bootloader 将 FAT 负载放入 RAM,并把地址写入固件 FDT 的 `/chosen/linux,initrd-start` 和 `linux,initrd-end`。两个属性均使用 32 位或 64 位大端地址。范围需要包含完整的 512 字节扇区,并在 UEFI 使用期间保持保留。
|
||||
|
||||
@@ -162,6 +162,7 @@ kernel_args = ["-v", "serial=3", "debug=0x14e"]
|
||||
| `panic_screen` | 布尔 | 把 panic 屏幕打进负载内核 |
|
||||
| `trust_cache_sha256` | 数组 | 接受的 trust cache 哈希。用 `--owner-trust-cache` 传入的 owner 包跳过此列表 |
|
||||
| `kernel_args` | 数组 | 默认内核参数 |
|
||||
| `tools` | 布尔 | 在生成的菜单中加入 Tools;按[日志抓取步骤](/zh/porting/log-capture#firmware-setup)配置插件 |
|
||||
| `timeout` | 整数 | 菜单超时 |
|
||||
| `skip_setup_tool` | 字符串 | `--skip-setup` 使用的脚本 |
|
||||
|
||||
|
||||
Reference in new issue
Block a user