返回提交历史
Modified
AGENTS.md
+6
-0
Added
docs/BingCssMonacoUsb20261017.md
+51
-0
Added
docs/validation-results/BingCssMonacoUsb20261017.json
+144
-0
Added
scripts/physical-media-previous-import-tests.ps1
+98
-0
Modified
scripts/physical-media.ps1
+63
-10
XFEstudio/XFESystem
Preserve USB workspace when upgrading the verified Desktop image
2e39557
代码差异
5 个文件
+362
-10
@@ -1,5 +1,11 @@
1
1
# XFESystem 用户约定
2
2
3
2026-10-17 用户明确恢复写入授权,已将 **0.3.0-dev.4-bing-css-monaco.1 / Desktop USB 工作区单系统** 写入专用 USB `230222336207` / `5000000000002AEF`。源镜像保持 `e463fa94b7fa162662c330b0c0fa7d1f1e9ac21a05b57086a66a3d52900c18de`;完整 `268435456` 字节容量调整及工作区恢复后的预期/实际 SHA256 均为 `5248ef1bf450c1cff99a44830bd115100c924173f802c64110f0edf330fbc473`,真实盘尾 GPT `ActualLastLba=500118191` 通过。**已有 64 MiB 工作区已实际备份并逐字节恢复**,SHA256 `b2c02a637875fdea037978e837bdba80e1c9fe0fa151712faaa3bafa841fbeab`,位置随新版 FAT 分配迁移,不清空用户文件和设置。
4
5
初次更新因两版自带 `UsbHello.dll` 哈希不同而在首个磁盘字节写入前拒绝,已打开的句柄随后关闭,原失败留存。写盘器增加仅适用 `IndependentCSharpUsb256` 的 `-PreviousWriteResult` / `-PreviousWriteResultSha256`:显式固定同一专用设备的历史成功回执,核验并锁定旧镜像、清单、启动回执、源码快照;只有与已验证旧版示例完全相符的文件允许备份升级,任意用户替换和额外文件继续拒绝覆盖。本次旧示例确实匹配上一版原文件,5632 字节已单独备份。17 项新增检查、原工作区升级保护、原物理写盘保护及 5 项交付分派检查通过;软件镜像与其原有 17 组、1666 项宿主/原生验收证据未改变,本轮未重跑完整应用验收。
6
7
最终辅助 PID `91856` 实际退出码 0 且已不存在,句柄关闭,fresh 身份相符、非系统/启动盘并保持离线。完成记录 `build/usb-media/XFEstudio-Desktop-BingCssMonaco-0.3.0-dev.4-retry-1792196976981/Completion.json` SHA256 `9c7fe55940092b5b9c24cf86ed397637f7f374efebbc7b8c108709efca1babad`,同目录 `Postflight.json` SHA256 `2e96bec8f4052f164833639b8e78ccf941b31759d22bfd7279ca7f36607ea0db`。详情 `docs/BingCssMonacoUsb20261017.md` / `docs/validation-results/BingCssMonacoUsb20261017.json`。原 ZIP 和主目录 EFI CRLF 差异保持原样;`DeliveryComplete=true`、`UsbWritten=true` 仅指本次实体介质更新,不能等同实体启动/网络/输入或完整发行验收,`FullReleaseQualified=false`。
8
3
9
2026-10-16 继续完成 **0.3.0-dev.4-bing-css-monaco.1 / Desktop 单系统实验镜像**。修复嵌套 flex 内在宽度、字形分段计量、循环百分比导致的导航裁剪和百分比重复解析;二维 transform 同步绘制/裁剪/命中/范围/冻结快照,官网箭头不再是大 L。Monaco 空会话已复现为短 .NET 正则被 GC 墙钟暂停触发 100 ms 超时,并被 undefined editor 掩盖。私有 Jint 增加有界字面替换及仅纯匹配/替换的 GC 暂停恢复:扣除已耗时、最多两次、不重放 JS 回调、不提高网站预算;保留首个真实初始化错误。最终四线程 384 次实际编辑器打开与 GC 压力无空会话、无原文丢失;不是永久无停顿保证。
4
10
5
11
真实 Edge 官网对照及原生 Bing v9 验收通过:主页照片/热点/二维码/旋转箭头、两次实际查询、各七个导航、实际 PNG 图标像素和两个结果页各六帧连续滚动至底部。新增 DOMParser/TreeWalker/Text.splitText、正确共享 Node 原型、Promise 微任务隔离、经典脚本 MIME/nosniff 规则和诚实统一 UA。固定 AngleSharp.Xml 1.2.0,完整精确提交 MIT 版权随包;拒绝 DTD/外部声明,未引入宿主 XML 网络/文件接口。初次 System.Xml 链接失败、提前截取占位图、验收调用参数错误、旧暂存锁文件及未指定 QEMU 的启动计划失败均保留,不计为成功。
@@ -0,0 +1,51 @@
1
# 2026-10-17 Desktop Bing/CSS/Monaco 实体 USB 更新
2
3
用户明确“现在可以写入U盘了”,恢复本次专用介质写入授权。已将原来通过验收的 **0.3.0-dev.4-bing-css-monaco.1** 写入 Desktop 单系统 U 盘,保留已有工作区。Console 没有写入,原 ZIP、软件内核和镜像源文件保持原字节。
4
5
## 目标与写后验证
6
7
- USB:`lankxin T.Pssd USB 3.2`,序列号 `230222336207`,UniqueId `5000000000002AEF`;本次为磁盘 3,但选择和多次复核依靠完整设备身份。
8
- 实际容量 `256060514304` 字节,512 字节逻辑扇区,非系统/启动盘,写前后离线。
9
- 使用 `IndependentCSharpUsb256` 新计划及令牌;源码、当前验收回执和旧版升级证据在打开目标前锁定。
10
- 完整原镜像回读后恢复工作区,再调整 GPT;随后完整回读 `268435456` 字节,并核验真实末尾的 GPT 表和备份头。`ActualLastLba=500118191`。
11
- 辅助进程 PID `91856` 已实际退出,退出码 0;所有句柄关闭,独立 fresh 磁盘枚举确认身份相符、非系统/启动盘、保持离线。
12
13
| 内容 | SHA256 |
14
| --- | --- |
15
| 未修改的源镜像 | `e463fa94b7fa162662c330b0c0fa7d1f1e9ac21a05b57086a66a3d52900c18de` |
16
| 内核 | `5ecfc11d5d9d8b1d70e3be55d413089f0d8b8ec98fd27e6f3cf9d86b1d965680` |
17
| 恢复工作区及适配容量后的预期/实际完整镜像 | `5248ef1bf450c1cff99a44830bd115100c924173f802c64110f0edf330fbc473` |
18
| 原有 64 MiB 工作区备份及恢复内容 | `b2c02a637875fdea037978e837bdba80e1c9fe0fa151712faaa3bafa841fbeab` |
19
| 写入完成回执 | `9c7fe55940092b5b9c24cf86ed397637f7f374efebbc7b8c108709efca1babad` |
20
| 写后核对回执 | `2e96bec8f4052f164833639b8e78ccf941b31759d22bfd7279ca7f36607ea0db` |
21
22
已有工作区从字节偏移 `139294720` 迁移到新 FAT 分配的 `191322624`,完整 `67108864` 字节备份后逐字节恢复。完整镜像预期哈希同时包含该工作区覆盖区和 GPT 几何变化,因此不同于发行包源镜像哈希。
23
24
## 首次拒绝与旧版示例升级
25
26
首次写盘器发现现有 `UserFiles/UsbHello.dll` 与新版默认示例哈希不同,保护检查在首个磁盘字节写入前拒绝更新,已经打开的目标句柄随后关闭。记录保留在:
27
28
`build/usb-media/XFEstudio-Desktop-BingCssMonaco-0.3.0-dev.4-1792196697603/`
29
30
旧版原示例 SHA256 为 `a53f9369ad37786fd109b0a418f38366a0e32779ee67c8890f7aed3a8cc9300c`,新版为 `e25d6eadaae9c392aab086cc1610d31a2390f65b5349a7a4ec436609c3ca6d19`。直接放宽任意同名 DLL 检查会覆盖用户替换文件,因此本次增加明确的历史发行绑定:
31
32
1. `-PreviousWriteResult` 必须同时给出调用者已固定的 `-PreviousWriteResultSha256`,且仅支持 USB 工作区升级。
33
2. 历史回执必须为同一序列号和 UniqueId 的成功写入,完整回读和盘尾 GPT 通过;旧镜像、清单、启动回执及源码快照的哈希必须与该回执一致。
34
3. 旧启动回执必须确认其镜像、源码快照及 USB 持久化验收。上述旧证据进入新计划的令牌绑定,写入前保持文件锁定。
35
4. 实体盘中同名文件只有与该已验证旧版原示例完全一致时才允许备份后升级;任意用户替换文件、额外根文件和额外导入文件仍拒绝覆盖。
36
37
本次固定的上一版完成回执 SHA256 为 `89fb40a03274085352d4f1366fb96a217982d30bcb3d19914cf93bd25461fe53`。实际盘内示例匹配该旧版原文件,完整 5632 字节已独立备份并哈希回读;原有工作区同步完整备份。之后新计划重试写入并完成上述全部验证。旧失败目录的 `resolved-by-write.json` 关联新成功记录,没有覆盖原始失败。
38
39
## 验证与证据
40
41
Windows PowerShell 5.1 的 17 项新增检查覆盖固定历史证据、错误设备身份、缺失/错误哈希、失败或不完整历史验收、变化的旧镜像/启动回执、原示例备份、完整工作区恢复、任意用户替换拒绝以及令牌绑定。原有工作区升级保护和物理写盘保护检查通过;交付分派的 5 项离线检查通过。这些测试只操作普通文件,没有使用实体盘。
42
43
本次实际写入使用的镜像仍绑定原有 17 组、1666 项宿主检查及原生 Bing v9、Monaco 编辑、文档、终端、USB 双冷启动和其他数据卷验收;完整应用验收本轮没有重复执行。主目录原有 EFI CRLF 差异的原始 SHA256 仍为 `9536c5475483ff61441b673ba6f7efa3beb579e3a48d3bba9dc05fc0dfb084b8`,未暂存。
44
45
成功写盘原始目录:
46
47
`build/usb-media/XFEstudio-Desktop-BingCssMonaco-0.3.0-dev.4-retry-1792196976981/`
48
49
其中保留 `Selection.json`、`DryPlan.json`、`WritePlan.json`、`Completion.json`、`Postflight.json`、实际进程退出记录、日志和两个用户数据保护备份。摘要见 `docs/validation-results/BingCssMonacoUsb20261017.json`,原镜像验收见 `docs/validation-results/BingCssMonaco20261016.json`。
50
51
`DeliveryComplete=true`、`UsbWritten=true` 表示这次专用实体介质更新完成。实体启动、网络和输入没有因这次写盘取得新的验收,完整 Chromium 兼容、GPU/CUDA、SMP 和长期稳定性仍不属于本次结果,`FullReleaseQualified=false`。
@@ -0,0 +1,144 @@
1
{
2
"Kind": "XfeBingCssMonacoUsbDelivery20261017",
3
"Version": "0.3.0-dev.4-bing-css-monaco.1",
4
"Edition": "Desktop",
5
"DeploymentPolicy": "SingleEditionOnly",
6
"Date": "2026-10-17",
7
"UserAuthorizedPhysicalWrite": true,
8
"ImageDeliveryComplete": true,
9
"DeliveryComplete": true,
10
"UsbWritten": true,
11
"PhysicalDiskOpened": true,
12
"FullReleaseQualified": false,
13
"PhysicalBootAcceptancePassed": false,
14
"StorageEnabled": true,
15
"RamOnly": false,
16
"SourceRoot": "C:\\Users\\XFEstudio\\.codex\\worktrees\\browser-load-speed\\XFESystem",
17
"ImagePath": "C:\\Users\\XFEstudio\\.codex\\worktrees\\browser-load-speed\\XFESystem\\build\\IndependentKernel\\Proof-1792113213603993800\\System.img",
18
"ImageSha256": "e463fa94b7fa162662c330b0c0fa7d1f1e9ac21a05b57086a66a3d52900c18de",
19
"ImageBytes": 268435456,
20
"SourceImageUnchanged": true,
21
"KernelSha256": "5ecfc11d5d9d8b1d70e3be55d413089f0d8b8ec98fd27e6f3cf9d86b1d965680",
22
"OriginalZip": "dist/XFESystem-Desktop-Independent-USB-0.3.0-dev.4-bing-css-monaco.1-1792113907524-4bb5edd7.zip",
23
"OriginalZipSha256": "235e3bfb2428070097d3e6a2a2d48fedc21055ef3eea5f1c4a8d2557efd4149b",
24
"PreviousImageOnlyReport": "docs/validation-results/BingCssMonaco20261016.json",
25
"OriginalHostSuites": 17,
26
"OriginalHostChecks": 1666,
27
"FullHostSuitesRerunThisRound": false,
28
"FinalDeliveryGate": {
29
"Kind": "XfeIndependentFinalDeliveryGate",
30
"Passed": true,
31
"Method": "Open.ps1 -ValidateOnly",
32
"LauncherPath": "C:\\Users\\XFEstudio\\.codex\\worktrees\\browser-load-speed\\XFESystem\\Tools\\IndependentKernel\\Open.ps1",
33
"LauncherSha256": "6df41e37899a3b4485efac895eef4319313a9d090fbe0ed81190d11d2c00f525",
34
"ImageSha256": "e463fa94b7fa162662c330b0c0fa7d1f1e9ac21a05b57086a66a3d52900c18de",
35
"BootResultSha256": "a15a69581e8502577ce434b3db07fa9d343f2e58558ef70a129f7e24b86d9878",
36
"EvidenceHarnessSha256": {
37
"Tools/IndependentKernel/TestBoot.py": "4b1a682938966992b0eaa29a7d8cd4eafabad1d9cdb89a833f584d697bb86370",
38
"Tools/IndependentKernel/IndependentBingEvidence.py": "499cf62ca48181b28e4fd64dcbe99323c1751289aee061c65505729a634b0c8d",
39
"Tools/IndependentKernel/IndependentDocumentEvidence.py": "de08fd45747481a29808cfeabaec49ded4abfb7a5e0ae739e8c6ab01419e7909",
40
"Tools/IndependentKernel/TestUsbStorage.py": "f7d89268d0dae145d638ea3369d9536c8aee928ebce101c0402862d88040f14c",
41
"Tools/CSharpBoot/ReadImage.py": "85d29000e7e655e2db29805bcfeab8b49bf83cbfa8cfd4d346c15b12250db1df"
42
},
43
"Edition": "Desktop",
44
"ConsoleWorkflowPassed": false,
45
"BingNativeHttpsPassed": true,
46
"DocumentWorkflowPassed": true,
47
"TerminalWorkflowPassed": true,
48
"FullCssParityVerified": false,
49
"PhysicalInputHardwareAcceptancePassed": false,
50
"NoVmStarted": true,
51
"NoDiskWrites": true
52
},
53
"SingleEditionImageProof": {
54
"Kind": "XfeSingleEditionImageProof",
55
"Passed": true,
56
"Edition": "Desktop",
57
"KernelCount": 1,
58
"BootEntryCount": 1,
59
"SystemSelectionMenu": false,
60
"BootMenuTimeoutSeconds": 0,
61
"UsbWorkspace": true,
62
"FilePaths": [
63
"EFI/BOOT/BOOTX64.EFI",
64
"EFI/XFE/Limine.efi",
65
"Limine.conf",
66
"System/BootShim.json",
67
"System/Kernel.elf",
68
"UserFiles/UsbHello.dll",
69
"Workspace.bin"
70
],
71
"ConfigurationSha256": "cd184a4d0539f869460a9bb5d74ffd222f197e274f85df75df757a9241f8e050"
72
},
73
"UsbStorageAcceptancePassed": true,
74
"FreshDisk": {
75
"Number": 3,
76
"FriendlyName": "lankxin T.Pssd USB 3.2",
77
"SerialNumber": "230222336207",
78
"UniqueId": "5000000000002AEF",
79
"Size": 256060514304,
80
"LogicalSectorSize": 512,
81
"BusType": "USB",
82
"IsOffline": true,
83
"IsSystem": false,
84
"IsBoot": false
85
},
86
"Verification": {
87
"ImageBytesVerified": 268435456,
88
"ExpectedAdjustedImageSha256": "5248ef1bf450c1cff99a44830bd115100c924173f802c64110f0edf330fbc473",
89
"ActualAdjustedImageSha256": "5248ef1bf450c1cff99a44830bd115100c924173f802c64110f0edf330fbc473",
90
"ActualLastLba": 500118191,
91
"ActualTailBackupGptVerified": true,
92
"FullImageVerified": true
93
},
94
"PreservedWorkspace": {
95
"SourceOffset": 139294720,
96
"DestinationOffset": 191322624,
97
"Bytes": 67108864,
98
"SnapshotPath": "C:\\Users\\XFEstudio\\Desktop\\work\\CSharp\\GitHub\\XFEstudio\\XFESystem\\build\\usb-media\\XFEstudio-Desktop-BingCssMonaco-0.3.0-dev.4-retry-1792196976981\\PreservedWorkspace-3f66d1f6b5bd4e2289a3ec35a84e7ee4.bin",
99
"Sha256": "b2c02a637875fdea037978e837bdba80e1c9fe0fa151712faaa3bafa841fbeab",
100
"Restored": true
101
},
102
"PreservedStockImport": {
103
"SnapshotPath": "C:\\Users\\XFEstudio\\Desktop\\work\\CSharp\\GitHub\\XFEstudio\\XFESystem\\build\\usb-media\\XFEstudio-Desktop-BingCssMonaco-0.3.0-dev.4-retry-1792196976981\\PreviousStockImport-188860af4aac4d6db292519b9622e619-UsbHello.dll",
104
"Sha256": "a53f9369ad37786fd109b0a418f38366a0e32779ee67c8890f7aed3a8cc9300c",
105
"Bytes": 5632,
106
"PreviousCompletionSha256": "89fb40a03274085352d4f1366fb96a217982d30bcb3d19914cf93bd25461fe53",
107
"CandidateSha256": "e25d6eadaae9c392aab086cc1610d31a2390f65b5349a7a4ec436609c3ca6d19",
108
"ReplacementVerified": true
109
},
110
"HelperExitCode": 0,
111
"HelperCompleted": true,
112
"HelperProcessStillExists": false,
113
"HandlesClosed": true,
114
"FreshIdentityMatches": true,
115
"CompletionPath": "build/usb-media/XFEstudio-Desktop-BingCssMonaco-0.3.0-dev.4-retry-1792196976981/Completion.json",
116
"CompletionSha256": "9c7fe55940092b5b9c24cf86ed397637f7f374efebbc7b8c108709efca1babad",
117
"PostflightPath": "build/usb-media/XFEstudio-Desktop-BingCssMonaco-0.3.0-dev.4-retry-1792196976981/Postflight.json",
118
"PostflightSha256": "2e96bec8f4052f164833639b8e78ccf941b31759d22bfd7279ca7f36607ea0db",
119
"InitialRefusal": {
120
"Path": "build/usb-media/XFEstudio-Desktop-BingCssMonaco-0.3.0-dev.4-1792196697603/Completion.json",
121
"Sha256": "6ef8241bd02e6f422ef6589c408b5f4d6dfefe6b1e25bcb54830ff2df4a90240",
122
"PhysicalDiskOpened": true,
123
"DiskBytesWritten": false,
124
"HandlesClosed": true,
125
"Reason": "Old stock UsbHello.dll hash differed from candidate default",
126
"ResolvedByPinnedPreviousRelease": true,
127
"ResolutionPath": "build/usb-media/XFEstudio-Desktop-BingCssMonaco-0.3.0-dev.4-1792196697603/resolved-by-write.json"
128
},
129
"WriterSha256": "75560a4efcaf68c5c9f16982b8f0bdbfa122fcd8a19c636574008bd881b63307",
130
"Guards": {
131
"Kind": "XfeUsbUpdateGuardResults",
132
"Passed": true,
133
"PreviousStockImportChecks": 17,
134
"DeliveryGateChecks": 5,
135
"OriginalWorkspaceUpdateGuardsPassed": true,
136
"OriginalPhysicalMediaGuardsPassed": true,
137
"Runtime": "Windows PowerShell 5.1",
138
"PhysicalDiskUsedForTests": false,
139
"FullHostSuitesRerun": false,
140
"FinishedUtc": "2026-10-17T00:29:37.8527131Z"
141
},
142
"UnrelatedMainEfiSha256": "9536c5475483ff61441b673ba6f7efa3beb579e3a48d3bba9dc05fc0dfb084b8",
143
"FinishedUtc": "2026-10-17T00:30:50.4589773Z"
144
}
@@ -0,0 +1,98 @@
1
# Real previous-release evidence and regular-file migration tests. No raw disks.
2
[CmdletBinding()]
3
param([Parameter(Mandatory=$true)][string]$Image,
4
[Parameter(Mandatory=$true)][string]$PreviousWriteResult,
5
[Parameter(Mandatory=$true)][string]$PreviousWriteResultSha256)
6
$ErrorActionPreference='Stop'
7
$candidate=$Image
8
$previousPath=$PreviousWriteResult
9
$previousHash=$PreviousWriteResultSha256
10
. (Join-Path $PSScriptRoot 'physical-media.ps1') -LoadFunctionsOnly
11
$directory=Join-Path (Join-Path $PSScriptRoot '../build') ('PreviousStockImportTests-'+[Guid]::NewGuid().ToString('N'))
12
[void][IO.Directory]::CreateDirectory($directory)
13
$disk=[pscustomobject]@{Number=3;SerialNumber='230222336207';UniqueId='5000000000002AEF';Size=[uint64]256060514304;BusType='USB';LogicalSectorSize=512}
14
$script:checks=0
15
function Check([bool]$Condition,[string]$Message){if(!$Condition){throw $Message};$script:checks++}
16
function Refuse([scriptblock]$Action,[string]$Message){$failed=$false;try{& $Action | Out-Null}catch{$failed=$true};Check $failed $Message}
17
function Fixture($Receipt,[string]$Name){$path=Join-Path $directory $Name;$Receipt | ConvertTo-Json -Depth 20 | Set-Content -LiteralPath $path -Encoding UTF8;return $path}
18
$prior=Get-Content -LiteralPath $previousPath -Raw -Encoding UTF8 | ConvertFrom-Json
19
$originalImageHash=(Get-FileHash -LiteralPath $candidate -Algorithm SHA256).Hash
20
$originalOldHash=(Get-FileHash -LiteralPath $prior.Plan.image -Algorithm SHA256).Hash
21
$known=Get-XfePreviousStockImport $previousPath $previousHash $disk
22
Check ($known.DefaultImportSha256 -ceq $prior.ExperimentalEvidence.DefaultImportSha256 -and $known.EvidenceLocks.Count -eq 5) 'Previous stock release was not bound.'
23
Refuse {Get-XfePreviousStockImport $previousPath '' $disk} 'Missing pin was accepted.'
24
Refuse {Get-XfePreviousStockImport $previousPath ('0'*64) $disk} 'Wrong completion pin was accepted.'
25
$disk.SerialNumber='another-usb'
26
Refuse {Get-XfePreviousStockImport $previousPath $previousHash $disk} 'Wrong serial was accepted.'
27
$disk.SerialNumber='230222336207';$disk.UniqueId='another-unique-id'
28
Refuse {Get-XfePreviousStockImport $previousPath $previousHash $disk} 'Wrong unique ID was accepted.'
29
$disk.UniqueId='5000000000002AEF'
30
foreach($change in @('failed','not-persistent','incomplete-readback','changed-image','changed-boot')) {
31
$fixture=Get-Content -LiteralPath $previousPath -Raw -Encoding UTF8 | ConvertFrom-Json
32
switch($change) {
33
'failed' {$fixture.Status='failed'}
34
'not-persistent' {$fixture.ExperimentalEvidence.PersistentConfigurationVerified=$false}
35
'incomplete-readback' {$fixture.Verification.FullImageVerified=$false}
36
'changed-image' {$path=Join-Path $directory 'changed.img';[IO.File]::WriteAllBytes($path,[byte[]]@(1,2,3));$fixture.ExperimentalEvidence.ImagePath=$path}
37
'changed-boot' {
38
$boot=Get-Content -LiteralPath $fixture.ExperimentalEvidence.BootResultPath -Raw -Encoding UTF8 | ConvertFrom-Json
39
$boot.Passed=$false
40
$path=Fixture $boot 'failed-boot.json'
41
$fixture.ExperimentalEvidence.BootResultPath=$path
42
$fixture.ExperimentalEvidence.BootResultSha256=(Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash.ToLowerInvariant()
43
}
44
}
45
$path=Fixture $fixture ($change+'.json')
46
$hash=(Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash.ToLowerInvariant()
47
Refuse {Get-XfePreviousStockImport $path $hash $disk} ('Invalid previous release accepted: '+$change)
48
}
49
$manifest=Get-Content -LiteralPath ($candidate+'.json') -Raw -Encoding UTF8 | ConvertFrom-Json
50
$currentImport=(Get-Content -LiteralPath $previousPath -Raw -Encoding UTF8 | ConvertFrom-Json).ExperimentalEvidence.DefaultImportSha256
51
# A deliberately different candidate hash exercises the migration branch even
52
# when the supplied old/current fixtures happen to contain the same sample.
53
$differentImport='f'*64
54
if($differentImport -ceq $currentImport){$differentImport='e'*64}
55
$oldPath=Join-Path $directory 'Existing.img';Copy-Item -LiteralPath $prior.Plan.image -Destination $oldPath
56
$newPath=Join-Path $directory 'Updated.img';Copy-Item -LiteralPath $candidate -Destination $newPath
57
$old=$source=$target=$null
58
try {
59
$old=[IO.File]::Open($oldPath,[IO.FileMode]::Open,[IO.FileAccess]::ReadWrite,[IO.FileShare]::Read)
60
Refuse {Get-XfePreservedWorkspace $old $old.Length $directory $differentImport} 'Unidentified changed import was overwritten.'
61
$preserved=Get-XfePreservedWorkspace $old $old.Length $directory $differentImport $known
62
Check ($preserved.Bytes.Length -eq 64MB -and $preserved.StockImportBackup.Sha256 -ceq $currentImport -and
63
(Get-FileHash -LiteralPath $preserved.StockImportBackup.SnapshotPath -Algorithm SHA256).Hash.ToLowerInvariant() -ceq $currentImport) 'Previous stock sample was not backed up exactly.'
64
Check ((Get-FileHash -LiteralPath $preserved.SnapshotPath -Algorithm SHA256).Hash.ToLowerInvariant() -ceq $preserved.Sha256) 'Workspace backup was not exact.'
65
$source=[IO.File]::OpenRead($candidate)
66
$target=[IO.File]::Open($newPath,[IO.FileMode]::Open,[IO.FileAccess]::ReadWrite,[IO.FileShare]::Read)
67
$target.SetLength(300MB)
68
$patch=[pscustomobject]@{Offset=[uint64]$manifest.WorkspaceFirstLba*512;Bytes=$preserved.Bytes}
69
Write-XfeBytes $target $patch.Offset $patch.Bytes
70
Set-XfeAdjustedGpt $target (Get-XfeAdjustedGpt $source $target.Length)
71
$target.Flush($true)
72
$verification=Test-XfeAdjustedReadback $source $target $target.Length $patch
73
Check ($verification.FullImageVerified -and $verification.ActualTailBackupGptVerified) 'Cross-version full workspace restore failed.'
74
# A user replacement must still fail with valid old-release authorization.
75
$boot=Read-XfeBytes $old (2048*512) 512
76
$reserved=[BitConverter]::ToUInt16($boot,14);$fatSectors=[BitConverter]::ToUInt32($boot,36)
77
$clusterBytes=[int]$boot[13]*512
78
$fat=Read-XfeBytes $old ((2048+$reserved)*512) ($fatSectors*512)
79
$data=([uint64]2048+$reserved+2*[uint64]$fatSectors)*512
80
$root=@(Get-XfeFatDirectory $old $data $fat ([BitConverter]::ToUInt32($boot,44)) $clusterBytes)
81
$folder=@($root | Where-Object ShortName -CEQ 'USERFILE ')[0]
82
$file=@(Get-XfeFatDirectory $old $data $fat $folder.Cluster $clusterBytes)[0]
83
$offset=$data+([uint64]$file.Cluster-2)*$clusterBytes
84
$original=Read-XfeBytes $old $offset 512
85
$changed=[byte[]]$original.Clone();$changed[0]=$changed[0] -bxor 1
86
Write-XfeBytes $old $offset $changed
87
Refuse {Get-XfePreservedWorkspace $old $old.Length $directory $differentImport $known} 'A user replacement bypassed old-release validation.'
88
Write-XfeBytes $old $offset $original
89
$plain=Get-XfeMediaIdentity $disk @() 'image-hash' 'LegacyPhysical256' $null
90
$withPrevious=Get-XfeMediaIdentity $disk @() 'image-hash' 'LegacyPhysical256' $null $known
91
Check ((Get-XfeToken $plain) -cne (Get-XfeToken $withPrevious)) 'Previous-release authorization was omitted from the plan token.'
92
} finally {
93
foreach($stream in @($old,$source,$target)){if($stream){$stream.Dispose()}}
94
Check ((Get-FileHash -LiteralPath $candidate -Algorithm SHA256).Hash -ceq $originalImageHash -and
95
(Get-FileHash -LiteralPath $prior.Plan.image -Algorithm SHA256).Hash -ceq $originalOldHash -and
96
(Get-FileHash -LiteralPath $previousPath -Algorithm SHA256).Hash.ToLowerInvariant() -ceq $previousHash) 'Original accepted inputs changed.'
97
}
98
[ordered]@{Kind='XfePreviousStockImportTests';Passed=$true;Checks=$script:checks;PhysicalDiskOpened=$false;Directory=$directory} | ConvertTo-Json
@@ -11,6 +11,8 @@ param(
11
11
[string]$BootResult,
12
12
[string]$PythonPath = 'python',
13
13
[string]$ResultPath,
14
[string]$PreviousWriteResult,
15
[string]$PreviousWriteResultSha256,
14
16
[switch]$LoadFunctionsOnly
15
17
)
16
18
$ErrorActionPreference = 'Stop'
@@ -231,7 +233,40 @@ function Get-XfeFatDirectory($Target,[uint64]$Data,[byte[]]$Fat,[uint32]$Cluster
231
233
$Cluster=[BitConverter]::ToUInt32($Fat,[int]$Cluster*4) -band 268435455
232
234
}
233
235
}
234
function Get-XfePreservedWorkspace($Target,[uint64]$DiskBytes,[string]$BackupDirectory,[string]$DefaultImportSha256) {
236
function Get-XfePreviousStockImport([string]$Path,[string]$ExpectedHash,$Disk) {
237
if($ExpectedHash -cnotmatch '^[0-9a-f]{64}$'){throw 'A pinned previous completion SHA256 is required.'}
238
$receiptPath=(Resolve-Path -LiteralPath $Path).ProviderPath
239
if((Get-FileHash -LiteralPath $receiptPath -Algorithm SHA256).Hash.ToLowerInvariant() -cne $ExpectedHash){throw 'Previous USB completion hash changed.'}
240
$receipt=Get-Content -LiteralPath $receiptPath -Raw -Encoding UTF8 | ConvertFrom-Json
241
$old=$receipt.ExperimentalEvidence
242
if($receipt.Kind -cne 'XfePhysicalMediaOperation' -or $receipt.Profile -cne 'IndependentCSharpUsb256' -or
243
$receipt.Status -cne 'verified' -or $receipt.PhysicalDiskOpened -ne $true -or $receipt.HandlesClosed -ne $true -or
244
$receipt.FinalDiskState -cne 'offline' -or $receipt.Verification.FullImageVerified -ne $true -or
245
$receipt.Verification.ActualTailBackupGptVerified -ne $true -or $receipt.Verification.ImageBytesVerified -ne 256MB -or
246
$receipt.Plan.disk_serial -cne ([string]$Disk.SerialNumber).Trim() -or $receipt.Plan.disk_unique_id -cne ([string]$Disk.UniqueId).Trim() -or
247
$old.Profile -cne 'IndependentCSharpUsb256' -or $old.PersistentConfigurationVerified -ne $true -or
248
$old.UsbStorageAcceptancePassed -ne $true -or $old.DefaultImportSha256 -cnotmatch '^[0-9a-f]{64}$' -or
249
$old.ImageSha256 -cne $receipt.Plan.image_sha256 -or $old.ImageBytes -ne 256MB){
250
throw 'Previous completion is not a verified persistent release for this USB.'
251
}
252
$locks=@([pscustomobject]@{Path=$receiptPath;Sha256=$ExpectedHash})
253
foreach($pair in @(@($old.ImagePath,$old.ImageSha256),@($old.ImageManifestPath,$old.ImageManifestSha256),
254
@($old.BootResultPath,$old.BootResultSha256),@($old.SourceSnapshotPath,$old.SourceSnapshotSha256))) {
255
if([string]::IsNullOrWhiteSpace($pair[0]) -or $pair[1] -cnotmatch '^[0-9a-f]{64}$' -or
256
(Get-FileHash -LiteralPath $pair[0] -Algorithm SHA256).Hash.ToLowerInvariant() -cne $pair[1]){throw 'Previous release image or evidence changed.'}
257
$locks += [pscustomobject]@{Path=$pair[0];Sha256=$pair[1]}
258
}
259
$manifest=Get-Content -LiteralPath $old.ImageManifestPath -Raw -Encoding UTF8 | ConvertFrom-Json
260
$boot=Get-Content -LiteralPath $old.BootResultPath -Raw -Encoding UTF8 | ConvertFrom-Json
261
if($manifest.ImageSha256 -cne $old.ImageSha256 -or $manifest.UsbWorkspace -ne $true -or
262
$manifest.ImageBytes -ne 256MB -or $boot.Passed -ne $true -or $boot.SourcesUnchanged -ne $true -or
263
$boot.UsbStorageAcceptancePassed -ne $true -or $boot.ImageSha256 -cne $old.ImageSha256 -or
264
$boot.SourceSnapshotSha256 -cne $old.SourceSnapshotSha256){throw 'Previous release is not bound to its accepted image.'}
265
return [pscustomobject]@{ReceiptPath=$receiptPath;ReceiptSha256=$ExpectedHash;ImageSha256=$old.ImageSha256;
266
DefaultImportSha256=$old.DefaultImportSha256;EvidenceLocks=$locks}
267
}
268
function Get-XfePreservedWorkspace($Target,[uint64]$DiskBytes,[string]$BackupDirectory,[string]$DefaultImportSha256,$PreviousStockImport=$null) {
269
$stockBackup=$null
235
270
$header=Read-XfeBytes $Target 512 512
236
271
if([Text.Encoding]::ASCII.GetString($header,0,8) -cne 'EFI PART'){return $null}
237
272
$entry=Read-XfeBytes $Target 1024 128
@@ -265,10 +300,20 @@ function Get-XfePreservedWorkspace($Target,[uint64]$DiskBytes,[string]$BackupDir
265
300
}
266
301
$hasher=[Security.Cryptography.SHA256]::Create()
267
302
try {$importHash=([BitConverter]::ToString($hasher.ComputeHash($fileBytes))).Replace('-','').ToLowerInvariant()}finally{$hasher.Dispose()}
268
if($importHash -cne $DefaultImportSha256){throw 'UserFiles/UsbHello.dll contains changed user data; migrate it before updating. No disk data was overwritten.'}
303
if($importHash -cne $DefaultImportSha256){
304
# An explicitly pinned, successfully written previous release can
305
# identify an old stock example. Other user replacements still fail.
306
if(!$PreviousStockImport -or $importHash -cne $PreviousStockImport.DefaultImportSha256){throw 'UserFiles/UsbHello.dll contains changed user data; migrate it before updating. No disk data was overwritten.'}
307
$importSnapshot=Join-Path $BackupDirectory ('PreviousStockImport-'+[Guid]::NewGuid().ToString('N')+'-UsbHello.dll')
308
$backupStream=[IO.File]::Open($importSnapshot,[IO.FileMode]::CreateNew,[IO.FileAccess]::Write,[IO.FileShare]::Read)
309
try{$backupStream.Write($fileBytes,0,$fileBytes.Length);$backupStream.Flush($true)}finally{$backupStream.Dispose()}
310
if((Get-FileHash -LiteralPath $importSnapshot -Algorithm SHA256).Hash.ToLowerInvariant() -cne $importHash){throw 'Previous stock import backup verification failed; no disk data was overwritten.'}
311
$stockBackup=[pscustomobject]@{SnapshotPath=$importSnapshot;Sha256=$importHash;Bytes=$fileBytes.Length;
312
PreviousCompletionSha256=$PreviousStockImport.ReceiptSha256;CandidateSha256=$DefaultImportSha256;ReplacementVerified=$false}
313
}
269
314
}
270
315
}
271
if($workspace.Count -eq 0){return $null}
316
if($workspace.Count -eq 0){if($stockBackup){throw 'Previous persistent workspace is missing; update refused.'};return $null}
272
317
[uint32]$first=$workspace[0].Cluster;[uint32]$needed=67108864/$clusterBytes
273
318
for([uint32]$i=0;$i -lt $needed;$i++) {
274
319
[uint32]$cluster=$first+$i
@@ -284,15 +329,16 @@ function Get-XfePreservedWorkspace($Target,[uint64]$DiskBytes,[string]$BackupDir
284
329
[BitConverter]::ToUInt32($bytes,20) -ne (Get-XfeCrc32 ([byte[]]$bytes[0..19]))){throw 'Existing workspace descriptor is invalid; automatic overwrite refused.'}
285
330
$snapshot=Join-Path $BackupDirectory ('PreservedWorkspace-'+[Guid]::NewGuid().ToString('N')+'.bin')
286
331
[IO.File]::WriteAllBytes($snapshot,$bytes)
287
return [pscustomobject]@{Bytes=$bytes;OriginalOffset=$offset;SnapshotPath=$snapshot;Sha256=(Get-FileHash -LiteralPath $snapshot -Algorithm SHA256).Hash.ToLowerInvariant()}
332
return [pscustomobject]@{Bytes=$bytes;OriginalOffset=$offset;SnapshotPath=$snapshot;Sha256=(Get-FileHash -LiteralPath $snapshot -Algorithm SHA256).Hash.ToLowerInvariant();StockImportBackup=$stockBackup}
288
333
}
289
function Get-XfeMediaIdentity($Disk, $Partitions, [string]$ImageHash, [string]$Profile, $Evidence) {
334
function Get-XfeMediaIdentity($Disk, $Partitions, [string]$ImageHash, [string]$Profile, $Evidence, $PreviousStockImport=$null) {
290
335
$identity = '{0}|{1}|{2}|{3}|{4}|{5}|{6}' -f $Disk.Number, $Disk.UniqueId, ([string]$Disk.SerialNumber).Trim(), $Disk.Size, $Disk.BusType, $Disk.LogicalSectorSize, $ImageHash
291
336
if ($Profile -in @('CSharpExperimental128','IndependentCSharp128','IndependentCSharpUsb256','IndependentDualCSharp256')) {
292
337
$writerHash = (Get-FileHash -LiteralPath (Join-Path $PSScriptRoot 'physical-media.ps1') -Algorithm SHA256).Hash.ToLowerInvariant()
293
338
$verifierHash = (Get-FileHash -LiteralPath (Join-Path $PSScriptRoot 'physical-media-verify.py') -Algorithm SHA256).Hash.ToLowerInvariant()
294
339
$identity += '|{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}' -f $Profile,$Evidence.ImageManifestSha256,$Evidence.BootResultSha256,$Evidence.SourceSnapshotSha256,(Get-XfePartitionFingerprint $Partitions),$writerHash,$verifierHash,$Evidence.KernelProjectSha256
295
340
}
341
if($PreviousStockImport){$identity += '|previous-stock-import|'+$PreviousStockImport.ReceiptSha256}
296
342
return $identity
297
343
}
298
344
if ($LoadFunctionsOnly) { return }
@@ -309,6 +355,7 @@ try {
309
355
if ($ImageProfile -ceq 'IndependentDualCSharp256') {
310
356
throw 'Dual-system deployment was retired at the user request. Select one Console or Desktop image with IndependentCSharp128 (RAM) or IndependentCSharpUsb256 (USB workspace); no disk was opened.'
311
357
}
358
if(($PreviousWriteResult -or $PreviousWriteResultSha256) -and $ImageProfile -cne 'IndependentCSharpUsb256'){throw 'Previous stock import evidence is supported only for USB workspace updates.'}
312
359
if (-not $Image -or $DiskNumber -lt 0) { throw 'Specify -Image FILE.img and -DiskNumber N. Without -Write this only produces a review plan.' }
313
360
if ($env:OS -ne 'Windows_NT') { throw 'This script requires Windows Storage cmdlets.' }
314
361
$imagePath = (Resolve-Path -LiteralPath $Image).ProviderPath
@@ -335,7 +382,9 @@ $disk = Get-Disk -Number $DiskNumber -ErrorAction Stop
335
382
$parts = @(Get-Partition -DiskNumber $DiskNumber -ErrorAction Stop)
336
383
Assert-XfeDisk $disk $parts $imageInfo.Length
337
384
if ($ImageProfile -in @('CSharpExperimental128','IndependentCSharp128','IndependentCSharpUsb256','IndependentDualCSharp256')) { Assert-XfeExperimentalDisk $disk $parts $imageInfo.Length }
338
$identity = Get-XfeMediaIdentity $disk $parts $imageHash $ImageProfile $evidence
385
$previousStock=$null
386
if($PreviousWriteResult -or $PreviousWriteResultSha256){$previousStock=Get-XfePreviousStockImport $PreviousWriteResult $PreviousWriteResultSha256 $disk}
387
$identity = Get-XfeMediaIdentity $disk $parts $imageHash $ImageProfile $evidence $previousStock
339
388
$token = Get-XfeToken $identity
340
389
$plan = [ordered]@{
341
390
schema = 1
@@ -354,6 +403,7 @@ $plan = [ordered]@{
354
403
image_sha256 = $imageHash
355
404
image_profile = $ImageProfile
356
405
experimental_evidence = $evidence
406
previous_stock_import = $previousStock
357
407
full_release_qualified = $false
358
408
stability_passed = $false
359
409
cuda_execution_verified = $false
@@ -386,7 +436,7 @@ $freshDisk = Get-Disk -Number $DiskNumber -ErrorAction Stop
386
436
$freshParts = @(Get-Partition -DiskNumber $DiskNumber -ErrorAction Stop)
387
437
Assert-XfeDisk $freshDisk $freshParts $imageInfo.Length
388
438
if ($ImageProfile -in @('CSharpExperimental128','IndependentCSharp128','IndependentCSharpUsb256','IndependentDualCSharp256')) { Assert-XfeExperimentalDisk $freshDisk $freshParts $imageInfo.Length }
389
$freshIdentity = Get-XfeMediaIdentity $freshDisk $freshParts $imageHash $ImageProfile $evidence
439
$freshIdentity = Get-XfeMediaIdentity $freshDisk $freshParts $imageHash $ImageProfile $evidence $previousStock
390
440
if ($freshIdentity -cne $identity) { throw 'Target identity changed since the plan; refusing the write.' }
391
441
$rawPath = '\\.\PhysicalDrive' + $DiskNumber
392
442
$target = $null
@@ -416,13 +466,14 @@ try {
416
466
foreach($artifact in $evidence.AdditionalEvidenceLocks){$evidenceLocks += Open-XfeLockedImage $artifact.Path $artifact.Sha256}
417
467
}
418
468
}
469
if($previousStock){foreach($artifact in $previousStock.EvidenceLocks){$evidenceLocks += Open-XfeLockedImage $artifact.Path $artifact.Sha256}}
419
470
# Recheck the target after hashing while the source is locked. No disk state
420
471
# changes until both exact identities and the locked source hash are valid.
421
472
$lockedDisk=Get-Disk -Number $DiskNumber -ErrorAction Stop
422
473
$lockedParts=@(Get-Partition -DiskNumber $DiskNumber -ErrorAction Stop)
423
474
Assert-XfeDisk $lockedDisk $lockedParts $imageInfo.Length
424
475
if ($ImageProfile -in @('CSharpExperimental128','IndependentCSharp128','IndependentCSharpUsb256','IndependentDualCSharp256')) { Assert-XfeExperimentalDisk $lockedDisk $lockedParts $imageInfo.Length }
425
$lockedIdentity=Get-XfeMediaIdentity $lockedDisk $lockedParts $imageHash $ImageProfile $evidence
476
$lockedIdentity=Get-XfeMediaIdentity $lockedDisk $lockedParts $imageHash $ImageProfile $evidence $previousStock
426
477
if($lockedIdentity -cne $identity){throw 'Target identity changed while locking the source; refusing before any target mutation.'}
427
478
Set-Disk -Number $DiskNumber -IsOffline $true -ErrorAction Stop
428
479
$log.Stage='copying-physical-image'
@@ -438,13 +489,14 @@ try {
438
489
$openedParts=@(Get-Partition -DiskNumber $DiskNumber -ErrorAction Stop)
439
490
Assert-XfeDisk $openedDisk $openedParts $imageInfo.Length
440
491
if ($ImageProfile -in @('CSharpExperimental128','IndependentCSharp128','IndependentCSharpUsb256','IndependentDualCSharp256')) { Assert-XfeExperimentalDisk $openedDisk $openedParts $imageInfo.Length }
441
if ((Get-XfeMediaIdentity $openedDisk $openedParts $imageHash $ImageProfile $evidence) -cne $identity) { throw 'Target identity changed while opening its handle; refusing before any disk byte was written.' }
492
if ((Get-XfeMediaIdentity $openedDisk $openedParts $imageHash $ImageProfile $evidence $previousStock) -cne $identity) { throw 'Target identity changed while opening its handle; refusing before any disk byte was written.' }
442
493
$workspacePatch=$null
443
494
if($ImageProfile -ceq 'IndependentCSharpUsb256') {
444
$preserved=Get-XfePreservedWorkspace $target ([uint64]$openedDisk.Size) (Split-Path -Parent ([IO.Path]::GetFullPath($ResultPath))) $evidence.DefaultImportSha256
495
$preserved=Get-XfePreservedWorkspace $target ([uint64]$openedDisk.Size) (Split-Path -Parent ([IO.Path]::GetFullPath($ResultPath))) $evidence.DefaultImportSha256 $previousStock
445
496
if($preserved) {
446
497
$workspacePatch=[pscustomobject]@{Offset=[uint64]$evidence.WorkspaceFirstLba*512;Bytes=$preserved.Bytes}
447
498
$log.PreservedWorkspace=[ordered]@{SourceOffset=$preserved.OriginalOffset;DestinationOffset=$workspacePatch.Offset;Bytes=67108864;SnapshotPath=$preserved.SnapshotPath;Sha256=$preserved.Sha256;Restored=$false}
499
if($preserved.StockImportBackup){$log.PreservedStockImport=$preserved.StockImportBackup}
448
500
}
449
501
}
450
502
[void]$source.Seek(0,[IO.SeekOrigin]::Begin);[void]$target.Seek(0,[IO.SeekOrigin]::Begin)
@@ -471,6 +523,7 @@ try {
471
523
$target.Flush($true)
472
524
$log.Stage='verifying-complete-adjusted-image-and-tail'
473
525
$log.Verification = Test-XfeAdjustedReadback $source $target ([uint64]$lockedDisk.Size) $workspacePatch
526
if($log.PreservedStockImport){$log.PreservedStockImport.ReplacementVerified=$true}
474
527
$log.Status='verified'
475
528
$log.FinalDiskState='offline'
476
529
Write-Host "Written and read-back verified disk $DiskNumber. GPT backup relocated to the physical disk end. Disk remains OFFLINE; disconnect the USB safely or reboot to UEFI."