diff --git a/.github/workflows/miru-h40-build.yml b/.github/workflows/miru-h40-build.yml index 50a78961276a..1cf38b0c063d 100644 --- a/.github/workflows/miru-h40-build.yml +++ b/.github/workflows/miru-h40-build.yml @@ -1,245 +1,82 @@ -name: Miru H.40 4.14.269 kernel and external modules +name: Miru H.40 Linux 4.14.287 diagnostic candidate materialization on: - push: - branches: - - miru-h40 pull_request: - branches: - - miru-h40 - types: - - opened - - reopened - - synchronize - - ready_for_review - workflow_dispatch: + branches: [miru-h40] + types: [opened, reopened, synchronize] permissions: - contents: read + contents: write + +concurrency: + group: miru-h40-lts287-candidate-diag26-${{ github.event.pull_request.number }} + cancel-in-progress: false env: - PRODUCTION_BASE: 4394ccbfa3805ce392b65b3ea148ff1eb084a974 - ANDROID_STABLE_TARGET: 0eec6f6001d15bb1108835a642ec4637d75eef19 - VENDOR_SHA: 125ff7d0153cbb3aaa8f9fd618c33b7f728d7798 - EXPECTED_RELEASE: 4.14.269-miru-h40-lts269-14d41d8-ci3+ - MAKEFILE_BUILD_269_BLOB: ee3b37a3bf6a586b74fe00f9e39ca5e77f08b6d3 + PRODUCTION_SHA: 61371a1024e341f434deaf61b79a05f73827260a + SOURCE_SHA: 705dd8a9d1e74a896a28d1a3efd6ff30fcc4e3b4 + SOURCE_BRANCH: miru-h40-lts287-source-diag26 + STABLE_287_SHA: 1048779a1d7dcf0b5c150188decafa21c19821e4 + DIAG25_HEAD: eb04d54f581da4257a331a816444bd6fe88b1ae1 + TARGET_BRANCH: miru-h40-lts287-full287-extconfix-diag26 + FIXED_EXTCON_BLOB: 3643c82ca1532c62d5596cff8e05878a4d52543f + EARLY_RANDOM_BLOB: c498b09b1b36b6cc9d34a16b08422e9299bc4a02 jobs: - production-kernel-and-modules: - if: >- - github.event_name != 'pull_request' || - github.event.pull_request.head.repo.full_name == github.repository + materialize-candidate: + if: github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-24.04 - timeout-minutes: 180 - + timeout-minutes: 30 steps: - - name: Checkout requested 4.14.269 revision + - name: Checkout exact preparation head uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} - fetch-depth: 0 - - - name: Verify 4.14.269 source, ancestry, and device fixes - shell: bash - run: | - set -Eeuo pipefail - git fetch --no-tags --depth=1 origin "${PRODUCTION_BASE}" - git fetch --no-tags --depth=1 origin "${ANDROID_STABLE_TARGET}" - git merge-base --is-ancestor "${PRODUCTION_BASE}" HEAD - git merge-base --is-ancestor "${ANDROID_STABLE_TARGET}" HEAD - git diff --check "${PRODUCTION_BASE}" HEAD - test -z "$(git ls-files -u)" - test "$(sed -n 's/^SUBLEVEL = //p' Makefile | head -n1)" = "269" - grep -Fq -- '- Semantically resolved conflicts: **22**' Documentation/miru/lts-4.14.269-conflicts.md - grep -Fq -- '- Remaining semantic conflicts: **0**' Documentation/miru/lts-4.14.269-conflicts.md - if git grep -nE '^(<<<<<<< .+|>>>>>>> .+)$' -- . \ - ':!Documentation/miru/lts-4.14.269-conflicts.md' \ - > source-conflict-markers.txt; then - cat source-conflict-markers.txt - exit 1 - else - : > source-conflict-markers.txt - fi - qrtr_fn="$(sed -n '/int qrtr_endpoint_post(/,/EXPORT_SYMBOL_GPL(qrtr_endpoint_post);/p' net/qrtr/qrtr.c)" - test "$(printf '%s\n' "${qrtr_fn}" | grep -c 'alloc_skb_with_frags(')" = 1 - test "$(printf '%s\n' "${qrtr_fn}" | grep -c 'qrtr_get_backup(len)')" = 1 - ! printf '%s\n' "${qrtr_fn}" | grep -Fq '__netdev_alloc_skb(NULL, len' - grep -Fq 'qcom_glink_rx_advance(glink, ALIGN(msglen, 8));' drivers/rpmsg/qcom_glink_native.c - irq_fn="$(sed -n '/static irqreturn_t qcom_glink_native_intr/,/return IRQ_HANDLED;/p' drivers/rpmsg/qcom_glink_native.c)" - ! printf '%s\n' "${irq_fn}" | grep -Fq 'if (ret == -ENOENT)' - { - echo "result=PASS" - echo "source_head=$(git rev-parse HEAD)" - echo "production_base=${PRODUCTION_BASE}" - echo "android_stable_target=${ANDROID_STABLE_TARGET}" - echo "expected_release=${EXPECTED_RELEASE}" - echo "qrtr_second_allocation=absent" - echo "glink_missing_channel_fifo_advance=present" - echo "glink_enoent_normalization=absent" - } | tee source-validation.txt + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 1 + persist-credentials: true - - name: Prepare pinned 4.14.269 build driver + - name: Materialize audited 4.14.287 candidate shell: bash run: | set -Eeuo pipefail - python3 scripts/miru/prepare_vendor_v6_linewise.py - python3 scripts/miru/inject_vendor_compat_v3_into_ci_build.py - sed -i 's/apply_vendor_lts190_compat_v3.py/apply_vendor_lts190_compat_v6.py/' \ - scripts/miru/ci_build_4.14.190.sh - python3 scripts/miru/insert_vendor_format_fixer.py python3 - <<'PY' from pathlib import Path - path = Path('scripts/miru/ci_build_4.14.190.sh') - text = path.read_text() - - def one(old, new): - global text - if old not in text: - raise SystemExit(f'missing expected build-driver text: {old}') - text = text.replace(old, new, 1) - - one('BASE_SHA=59858c8f798778f4e6c1c4449baba631e353600e', 'BASE_SHA=4394ccbfa3805ce392b65b3ea148ff1eb084a974') - one('STABLE_SHA=d2d05bcf4b4edf8d028fa420dee3c6644aa5b4ac', 'STABLE_SHA=0eec6f6001d15bb1108835a642ec4637d75eef19') - one("':!Documentation/miru/lts-4.14.190-conflicts.md'", "':!Documentation/miru/lts-4.14.269-conflicts.md'") - one('test "$(sed -n \'s/^SUBLEVEL = //p\' Makefile | head -n1)" = "190"', 'test "$(sed -n \'s/^SUBLEVEL = //p\' Makefile | head -n1)" = "269"') - one("grep -Fq -- '- Resolved conflicts: 28' Documentation/miru/lts-4.14.190-conflicts.md", "grep -Fq -- '- Semantically resolved conflicts: **22**' Documentation/miru/lts-4.14.269-conflicts.md") - one("grep -Fq -- '- Remaining conflicts: 0' Documentation/miru/lts-4.14.190-conflicts.md", "grep -Fq -- '- Remaining semantic conflicts: **0**' Documentation/miru/lts-4.14.269-conflicts.md") - one('echo "== Miru H.40 Android 4.14.190 CI build =="', 'echo "== Miru H.40 Android 4.14.269 production candidate build =="') - one('echo "kernel_version=4.14.190"', 'echo "kernel_version=4.14.269"') - one('echo "conflicts=28/28 resolved"', 'echo "conflicts=22/22 resolved"') - one('export KERNEL_LOCALVERSION=-miru-h40-lts190-ci1', 'export KERNEL_LOCALVERSION=-miru-h40-lts269-14d41d8-ci3') - one("grep -Fq 'CONFIG_LOCALVERSION=\"-miru-h40-lts190-ci1\"' \"${OUT_DIR}/.config\"", "grep -Fq 'CONFIG_LOCALVERSION=\"-miru-h40-lts269-14d41d8-ci3\"' \"${OUT_DIR}/.config\"") - one("grep -m1 '^Linux version 4\\.14\\.190-'", "grep -m1 '^Linux version 4\\.14\\.269-'") - one('git fetch --no-tags --depth=1 origin "${SCAFFOLD_SHA}"\n', '') - one('rm -rf "${ANDROID_ROOT}" "${VENDOR_SOURCE}"', 'rm -rf "${ANDROID_ROOT}" "${VENDOR_SOURCE}"\ngit worktree prune') - old = '''git cat-file -p "${SCAFFOLD_SHA}" > "${DIAG_DIR}/merge-scaffold.txt" - test "$(grep -c '^parent ' "${DIAG_DIR}/merge-scaffold.txt")" = "2" - grep -Fq "parent ${STABLE_SHA}" "${DIAG_DIR}/merge-scaffold.txt"''' - new = '''git merge-base --is-ancestor "${BASE_SHA}" HEAD - git merge-base --is-ancestor "${STABLE_SHA}" HEAD - { - echo "integration_base=${BASE_SHA}" - echo "stable_parent=${STABLE_SHA}" - git log -1 --format='head=%H%nparents=%P%nsubject=%s' HEAD - } > "${DIAG_DIR}/merge-scaffold.txt"''' - one(old, new) - path.write_text(text) + p = Path('scripts/miru/materialize_4.14.287_diag26_candidate.sh') + s = p.read_text() + + old_add = 'git -C "${wt}" add -- .github/workflows/miru-h40-build.yml drivers/extcon/extcon.c drivers/soc/qcom/early_random.c\n' + new_add = '''git -C "${wt}" add -- drivers/extcon/extcon.c drivers/soc/qcom/early_random.c + git -C "${wt}" add -f -- .github/workflows/miru-h40-build.yml + ''' + if s.count(old_add) != 1: + raise SystemExit(f'unexpected candidate add marker count: {s.count(old_add)}') + s = s.replace(old_add, new_add, 1) + + marker = "for stale in ('a79859d15ae0025897791a77654bcebeedc708ab'," + identity_fix = '''if s.count(' = 291') != 2: + raise SystemExit(f'unexpected bare sublevel count: {s.count(" = 291")}') + s = s.replace(' = 291', ' = 287') + if s.count(' = "291"') != 1: + raise SystemExit(f'unexpected quoted sublevel count: {s.count(chr(32) + "= \\\"291\\\"")}') + s = s.replace(' = "291"', ' = "287"') + if s.count('291-miru-h40-diag26') != 1: + raise SystemExit(f'unexpected release-token count: {s.count("291-miru-h40-diag26")}') + s = s.replace('291-miru-h40-diag26', '287-miru-h40-diag26') + ''' + if s.count(marker) != 1: + raise SystemExit(f'unexpected stale-token marker count: {s.count(marker)}') + s = s.replace(marker, identity_fix + marker, 1) + p.write_text(s) PY - grep -Fq 'kernel_version=4.14.269' scripts/miru/ci_build_4.14.190.sh - grep -Fq 'KERNEL_LOCALVERSION=-miru-h40-lts269-14d41d8-ci3' scripts/miru/ci_build_4.14.190.sh + bash scripts/miru/materialize_4.14.287_diag26_candidate.sh - - name: Build and validate the 4.14.269 kernel - shell: bash - run: | - set -Eeuo pipefail - bash scripts/miru/ci_build_4.14.190.sh - grep -Fq 'result=SUCCESS' build-diagnostics/build-summary.txt - grep -Fq "head=$(git rev-parse HEAD)" build-diagnostics/build-summary.txt - grep -Fq "banner=Linux version ${EXPECTED_RELEASE}" build-diagnostics/build-summary.txt - - - name: Build and ABI-validate exactly 32 matching external modules - shell: bash - run: | - set -Eeuo pipefail - python3 scripts/miru/prepare_external_modules_toolchain.py - python3 scripts/miru/prepare_external_pinctrl_headers.py - python3 scripts/miru/prepare_wlan_response_link.py - python3 - <<'PY' - from pathlib import Path - - path = Path('scripts/miru/build_external_modules_4.14.190.sh') - text = path.read_text() - old_release = '4.14.190-miru-h40-lts190-ci1+' - new_release = '4.14.269-miru-h40-lts269-14d41d8-ci3+' - old_hash = 'expected = "74ce588c69513197a354ef0032c2145e91ee0641"' - new_hash = 'expected = "ee3b37a3bf6a586b74fe00f9e39ca5e77f08b6d3"' - if old_release not in text: - raise SystemExit('missing old external-module release gate') - if old_hash not in text: - raise SystemExit('missing 4.14.190 Makefile.build integrity hash') - text = text.replace(old_release, new_release, 1) - text = text.replace(old_hash, new_hash, 1) - text = text.replace('4.14.190', '4.14.269').replace('lts190', 'lts269-14d41d8-ci3') - path.write_text(text) - PY - test "$(git -C "${RUNNER_TEMP}/android-root/kernel/msm-4.14" hash-object scripts/Makefile.build)" = "${MAKEFILE_BUILD_269_BLOB}" - bash scripts/miru/build_external_modules_4.14.190.sh - test "$(find "${RUNNER_TEMP}/miru-external-modules/dropin" -maxdepth 1 -type f -name '*.ko' | wc -l)" = 32 - grep -Fq 'errors=0' external-module-diagnostics/MODULE-ABI-REPORT.txt - test "$(grep -F ": ${EXPECTED_RELEASE} SMP preempt mod_unload modversions aarch64" external-module-diagnostics/vermagic.txt | wc -l)" = 32 - - - name: Assemble checksums and validation summary - shell: bash - run: | - set -Eeuo pipefail - KERNEL_DIR="${RUNNER_TEMP}/android-root/kernel/msm-4.14" - OUT_DIR="${RUNNER_TEMP}/android-root/out/h40-kernel" - MODULE_DIR="${RUNNER_TEMP}/miru-external-modules/dropin" - KERNEL_RELEASE="$(tr -d '\n' < "${OUT_DIR}/include/config/kernel.release")" - test "${KERNEL_RELEASE}" = "${EXPECTED_RELEASE}" - MODULE_COUNT="$(find "${MODULE_DIR}" -maxdepth 1 -type f -name '*.ko' | wc -l)" - test "${MODULE_COUNT}" = 32 - grep -Fq 'errors=0' external-module-diagnostics/MODULE-ABI-REPORT.txt - mkdir -p final-report - { - echo "result=SUCCESS" - echo "source_head=$(git rev-parse HEAD)" - echo "production_base=${PRODUCTION_BASE}" - echo "android_stable_target=${ANDROID_STABLE_TARGET}" - echo "vendor_source_commit=${VENDOR_SHA}" - echo "kernel_release=${KERNEL_RELEASE}" - echo "vermagic=${EXPECTED_RELEASE} SMP preempt mod_unload modversions aarch64" - echo "module_count=${MODULE_COUNT}" - echo "module_abi_errors=0" - echo "makefile_build_blob=${MAKEFILE_BUILD_269_BLOB}" - echo "run_id=${GITHUB_RUN_ID}" - echo "run_url=https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" - } | tee final-report/VALIDATION-SUMMARY.txt - cp source-validation.txt final-report/ - cp build-diagnostics/build-summary.txt final-report/KERNEL-BUILD-SUMMARY.txt - cp external-module-diagnostics/MODULE-ABI-REPORT.txt final-report/ - cp external-module-diagnostics/BUILD-MANIFEST.txt final-report/MODULE-BUILD-MANIFEST.txt - cp external-module-diagnostics/PACKAGE-SUMMARY.txt final-report/MODULE-PACKAGE-SUMMARY.txt - find "${RUNNER_TEMP}/android-root/out/h40-artifacts" -type f -print0 | sort -z | xargs -0 sha256sum > final-report/KERNEL-FILES-SHA256.txt - find "${MODULE_DIR}" -type f -print0 | sort -z | xargs -0 sha256sum > final-report/MODULE-FILES-SHA256.txt - sha256sum \ - "${RUNNER_TEMP}/android-root/out/miru-v3-modules-dropin-4.14.269.7z" \ - "${RUNNER_TEMP}/android-root/out/miru-v3-modules-dropin-4.14.269-audit.zip" \ - > final-report/MODULE-PACKAGES-SHA256.txt - - - name: Upload kernel output - if: always() - uses: actions/upload-artifact@v4 - with: - name: miru-h40-lts-4.14.269-ci3-build - path: ${{ runner.temp }}/android-root/out/h40-artifacts - if-no-files-found: warn - compression-level: 0 - retention-days: 30 - - - name: Upload matching external-module package + - name: Upload candidate materialization evidence if: always() uses: actions/upload-artifact@v4 with: - name: miru-v3-modules-dropin-4.14.269-ci3 - path: | - ${{ runner.temp }}/android-root/out/miru-v3-modules-dropin-4.14.269.7z - ${{ runner.temp }}/android-root/out/miru-v3-modules-dropin-4.14.269-audit.zip + name: miru-h40-lts287-candidate-diag26-evidence + path: candidate-287-evidence/ if-no-files-found: warn compression-level: 0 retention-days: 30 - - - name: Upload kernel, module, ABI, and checksum diagnostics - if: always() - uses: actions/upload-artifact@v4 - with: - name: miru-h40-lts-4.14.269-ci3-diagnostics - path: | - build-diagnostics - external-module-diagnostics - final-report - source-conflict-markers.txt - source-validation.txt - if-no-files-found: warn - retention-days: 30 diff --git a/scripts/miru/materialize_4.14.287_diag26.sh b/scripts/miru/materialize_4.14.287_diag26.sh new file mode 100644 index 000000000000..73a757038649 --- /dev/null +++ b/scripts/miru/materialize_4.14.287_diag26.sh @@ -0,0 +1,283 @@ +#!/usr/bin/env bash +set -Eeuo pipefail +set -x + +: "${PRODUCTION_SHA:?}" +: "${SCAFFOLD_283_SHA:?}" +: "${SOURCE_291_SHA:?}" +: "${STABLE_287_SHA:?}" +: "${STABLE_291_SHA:?}" +: "${FDT_292_SHA:?}" +: "${TARGET_BRANCH:?}" + +EVIDENCE="${GITHUB_WORKSPACE}/source-287-evidence" +mkdir -p "${EVIDENCE}" +trigger_sha="$(git rev-parse HEAD)" + +# Immutable branch and target gates. +test "$(git ls-remote origin refs/heads/miru-h40 | awk '{print $1}')" = "${PRODUCTION_SHA}" +test -z "$(git ls-remote origin "refs/heads/${TARGET_BRANCH}")" + +git fetch --no-tags origin \ + "${PRODUCTION_SHA}" "${SCAFFOLD_283_SHA}" "${SOURCE_291_SHA}" +if ! git remote get-url android-common >/dev/null 2>&1; then + git remote add android-common https://github.com/aosp-mirror/kernel_common.git +fi +git fetch --no-tags android-common \ + "${STABLE_287_SHA}" "${STABLE_291_SHA}" "${FDT_292_SHA}" + +# Proven ancestry and endpoint identity. +test "$(git rev-parse "${SCAFFOLD_283_SHA}^1")" = "${PRODUCTION_SHA}" +test "$(git rev-parse "${SOURCE_291_SHA}^1")" = "${SCAFFOLD_283_SHA}" +test "$(git rev-parse "${SOURCE_291_SHA}^2")" = "${STABLE_291_SHA}" +git merge-base --is-ancestor "${STABLE_287_SHA}" "${STABLE_291_SHA}" +! git merge-base --is-ancestor "${FDT_292_SHA}" "${STABLE_287_SHA}" +test "$(git show -s --format=%s "${STABLE_287_SHA}")" = 'Linux 4.14.287' +test "$(git show "${STABLE_287_SHA}:Makefile" | sed -n 's/^SUBLEVEL = //p' | head -n1)" = 287 +test "$(git show -s --format=%s "${STABLE_291_SHA}")" = 'Linux 4.14.291' + +ref_wt="${RUNNER_TEMP}/miru-291-downgraded-to-287" +merge_wt="${RUNNER_TEMP}/miru-287-source" +rm -rf "${ref_wt}" "${merge_wt}" + +# Mechanically downgrade the audited 4.14.291 source tree to 4.14.287. +git worktree add --detach "${ref_wt}" "${SOURCE_291_SHA}" +git -C "${ref_wt}" config user.name github-actions[bot] +git -C "${ref_wt}" config user.email 41898282+github-actions[bot]@users.noreply.github.com + +git diff --binary --full-index "${STABLE_291_SHA}" "${STABLE_287_SHA}" -- \ + > "${EVIDENCE}/stable-291-to-287.patch" +sha256sum "${EVIDENCE}/stable-291-to-287.patch" \ + > "${EVIDENCE}/stable-291-to-287.patch.sha256" +git diff --name-only "${STABLE_287_SHA}" "${STABLE_291_SHA}" | sort -u \ + > "${EVIDENCE}/post-287-stable-paths.txt" + +set +e +git -C "${ref_wt}" apply --3way --index \ + "${EVIDENCE}/stable-291-to-287.patch" \ + > "${EVIDENCE}/source-downgrade-apply.log" 2>&1 +downgrade_rc=$? +set -e +git -C "${ref_wt}" diff --name-only --diff-filter=U | sort -u \ + > "${EVIDENCE}/source-downgrade-conflicts.txt" +cat > "${EVIDENCE}/expected-source-downgrade-conflicts.txt" <<'EOF' +drivers/usb/host/xhci.c +drivers/usb/host/xhci.h +net/ipv4/tcp_output.c +EOF +test "${downgrade_rc}" = 1 +diff -u "${EVIDENCE}/expected-source-downgrade-conflicts.txt" \ + "${EVIDENCE}/source-downgrade-conflicts.txt" + +# Retain Miru/Qualcomm vendor code in the three overlap files, then remove only +# the Linux 4.14.288-4.14.291 semantic changes. +git -C "${ref_wt}" checkout --ours -- \ + drivers/usb/host/xhci.c drivers/usb/host/xhci.h net/ipv4/tcp_output.c + +python3 - "${ref_wt}/drivers/usb/host/xhci.c" <<'PY' +from pathlib import Path +import sys +p = Path(sys.argv[1]) +s = p.read_text() + +def one(old, new): + global s + if s.count(old) != 1: + raise SystemExit(f'unexpected xhci.c replacement count {s.count(old)} for {old!r}') + s = s.replace(old, new, 1) + +one('int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, u64 timeout_us)', + 'int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec)') +one('\t\t\t\t\t1, timeout_us);', '\t\t\t\t\t1, usec);') +one('int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us)', + 'int xhci_reset(struct xhci_hcd *xhci)') +one('\tret = xhci_handshake_check_state(xhci, &xhci->op_regs->command,\n\t\t\tCMD_RESET, 0, timeout_us);', + '\tret = xhci_handshake_check_state(xhci, &xhci->op_regs->command,\n\t\t\tCMD_RESET, 0, 10 * 1000 * 1000);') +one('\tret = xhci_handshake(&xhci->op_regs->status,\n\t\t\tSTS_CNR, 0, timeout_us);', + '\tret = xhci_handshake(&xhci->op_regs->status,\n\t\t\tSTS_CNR, 0, 10 * 1000 * 1000);') +if s.count('\txhci_reset(xhci, XHCI_RESET_SHORT_USEC);') != 2: + raise SystemExit('unexpected short-reset call count') +s = s.replace('\txhci_reset(xhci, XHCI_RESET_SHORT_USEC);', '\txhci_reset(xhci);') +if s.count('retval = xhci_reset(xhci, XHCI_RESET_LONG_USEC);') != 2: + raise SystemExit('unexpected long-reset call count') +s = s.replace('retval = xhci_reset(xhci, XHCI_RESET_LONG_USEC);', + 'retval = xhci_reset(xhci);') +one('\t\tretval = xhci_reset(xhci);\n\t\tspin_unlock_irq(&xhci->lock);\n\t\tif (retval)\n\t\t\treturn retval;', + '\t\txhci_reset(xhci);\n\t\tspin_unlock_irq(&xhci->lock);') +p.write_text(s) +PY + +python3 - "${ref_wt}/drivers/usb/host/xhci.h" <<'PY' +from pathlib import Path +import sys +p = Path(sys.argv[1]) +s = p.read_text() + +def one(old, new): + global s + if s.count(old) != 1: + raise SystemExit(f'unexpected xhci.h replacement count {s.count(old)} for {old!r}') + s = s.replace(old, new, 1) + +one('#define XHCI_RESET_LONG_USEC\t\t(10 * 1000 * 1000)\n#define XHCI_RESET_SHORT_USEC\t\t(250 * 1000)\n\n', '') +one('int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, u64 timeout_us);', + 'int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec);') +one('int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us);', + 'int xhci_reset(struct xhci_hcd *xhci);') +p.write_text(s) +PY + +python3 - "${ref_wt}/net/ipv4/tcp_output.c" <<'PY' +from pathlib import Path +import sys +p = Path(sys.argv[1]) +s = p.read_text() + +def one(old, new): + global s + if s.count(old) != 1: + raise SystemExit(f'unexpected tcp_output.c replacement count {s.count(old)} for {old!r}') + s = s.replace(old, new, 1) + +one('interval = READ_ONCE(net->ipv4.sysctl_tcp_probe_interval);', + 'interval = net->ipv4.sysctl_tcp_probe_interval;') +one('interval < READ_ONCE(net->ipv4.sysctl_tcp_probe_threshold)', + 'interval < net->ipv4.sysctl_tcp_probe_threshold') +one('\tint avail_wnd;\n', '') +one('\tavail_wnd = tcp_wnd_end(tp) - TCP_SKB_CB(skb)->seq;\n\n', '') +one('our retransmit of one segment serves as a zero window probe.', + 'our retransmit serves as a zero window probe.') +one('\tif (avail_wnd <= 0) {\n\t\tif (TCP_SKB_CB(skb)->seq != tp->snd_una)\n\t\t\treturn -EAGAIN;\n\t\tavail_wnd = cur_mss;\n\t}\n', + '\tif (!before(TCP_SKB_CB(skb)->seq, tcp_wnd_end(tp)) &&\n\t TCP_SKB_CB(skb)->seq != tp->snd_una)\n\t\treturn -EAGAIN;\n') +one('\tlen = cur_mss * segs;\n\tif (len > avail_wnd) {\n\t\tlen = rounddown(avail_wnd, cur_mss);\n\t\tif (!len)\n\t\t\tlen = avail_wnd;\n\t}\n', + '\tlen = cur_mss * segs;\n') +one('\t\tavail_wnd = min_t(int, avail_wnd, cur_mss);\n\t\tif (skb->len < avail_wnd)\n\t\t\ttcp_retrans_try_collapse(sk, skb, avail_wnd);', + '\t\tif (skb->len < cur_mss)\n\t\t\ttcp_retrans_try_collapse(sk, skb, cur_mss);') +one('\tint delta, amt;\n\n\tdelta = size - sk->sk_forward_alloc;\n\tif (delta <= 0)\n\t\treturn;\n\tamt = sk_mem_pages(delta);', + '\tint amt;\n\n\tif (size <= sk->sk_forward_alloc)\n\t\treturn;\n\tamt = sk_mem_pages(size);') +p.write_text(s) +PY + +git -C "${ref_wt}" add -- \ + drivers/usb/host/xhci.c drivers/usb/host/xhci.h net/ipv4/tcp_output.c + +test -z "$(git -C "${ref_wt}" diff --name-only --diff-filter=U)" +test -z "$(git -C "${ref_wt}" ls-files -u)" +git -C "${ref_wt}" diff --check --cached +test "$(sed -n 's/^SUBLEVEL = //p' "${ref_wt}/Makefile" | head -n1)" = 287 +! grep -Fq 'XHCI_RESET_LONG_USEC' "${ref_wt}/drivers/usb/host/xhci.h" +! grep -Fq 'XHCI_RESET_SHORT_USEC' "${ref_wt}/drivers/usb/host/xhci.h" +grep -Fq 'xhci_handshake_check_state(xhci, &xhci->op_regs->command' \ + "${ref_wt}/drivers/usb/host/xhci.c" +! grep -Fq 'READ_ONCE(net->ipv4.sysctl_tcp_probe_' \ + "${ref_wt}/net/ipv4/tcp_output.c" +! grep -Fq 'avail_wnd' "${ref_wt}/net/ipv4/tcp_output.c" +grep -Fq 'OPLUS_FEATURE_MODEM_DATA_NWPOWER' "${ref_wt}/net/ipv4/tcp_output.c" + +# Perform the real merge from the phone-confirmed 4.14.283 source scaffold. +git worktree add --detach "${merge_wt}" "${SCAFFOLD_283_SHA}" +git -C "${merge_wt}" config user.name github-actions[bot] +git -C "${merge_wt}" config user.email 41898282+github-actions[bot]@users.noreply.github.com +set +e +git -C "${merge_wt}" merge --no-commit --no-ff "${STABLE_287_SHA}" \ + > "${EVIDENCE}/miru-283-to-287-merge.log" 2>&1 +merge_rc=$? +set -e +test "${merge_rc}" = 0 -o "${merge_rc}" = 1 +git -C "${merge_wt}" diff --name-only --diff-filter=U | sort -u \ + > "${EVIDENCE}/miru-287-conflicts.txt" + +while IFS= read -r rel; do + [ -n "${rel}" ] || continue + if [ -e "${ref_wt}/${rel}" ] || [ -L "${ref_wt}/${rel}" ]; then + mkdir -p "$(dirname "${merge_wt}/${rel}")" + rm -rf "${merge_wt:?}/${rel}" + cp -a "${ref_wt}/${rel}" "${merge_wt}/${rel}" + git -C "${merge_wt}" add -- "${rel}" + else + git -C "${merge_wt}" rm -f --ignore-unmatch -- "${rel}" + fi +done < "${EVIDENCE}/miru-287-conflicts.txt" + +test -z "$(git -C "${merge_wt}" diff --name-only --diff-filter=U)" +test -z "$(git -C "${merge_wt}" ls-files -u)" +git -C "${merge_wt}" diff --check + +# The real merge tree must equal the mechanically downgraded audited source tree. +git -C "${ref_wt}" write-tree > "${EVIDENCE}/downgraded-reference-tree.txt" +git -C "${merge_wt}" write-tree > "${EVIDENCE}/actual-merge-tree.txt" +if ! cmp -s "${EVIDENCE}/downgraded-reference-tree.txt" "${EVIDENCE}/actual-merge-tree.txt"; then + git diff --name-status \ + "$(cat "${EVIDENCE}/downgraded-reference-tree.txt")" \ + "$(cat "${EVIDENCE}/actual-merge-tree.txt")" \ + > "${EVIDENCE}/tree-mismatch.txt" + { + echo result=FAIL + echo stage=tree-equivalence + echo "mismatch_count=$(wc -l < "${EVIDENCE}/tree-mismatch.txt")" + } | tee "${EVIDENCE}/SUMMARY.txt" + cat "${EVIDENCE}/tree-mismatch.txt" >&2 + exit 1 +fi + +# Required Miru/vendor semantics carried across the midpoint. +test "$(sed -n 's/^SUBLEVEL = //p' "${merge_wt}/Makefile" | head -n1)" = 287 +grep -Fq 'int of_fdt_get_ddrtype(void)' "${merge_wt}/drivers/of/fdt.c" +grep -Fq '"ddr_device_type", &len' "${merge_wt}/drivers/of/fdt.c" +grep -Fq 'extern int of_fdt_get_ddrtype(void);' "${merge_wt}/include/linux/of_fdt.h" +grep -Fq 'struct notifier_block' "${merge_wt}/lib/vsprintf.c" +grep -Fq 'register_random_ready_notifier' "${merge_wt}/lib/vsprintf.c" +grep -Fq 'CHACHA20_KEY_SIZE' "${merge_wt}/include/crypto/chacha.h" +grep -Fq 'void *dt_virt = fixmap_remap_fdt(dt_phys);' \ + "${merge_wt}/arch/arm64/kernel/setup.c" +! grep -Fq 'fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL)' \ + "${merge_wt}/arch/arm64/kernel/setup.c" +if git -C "${merge_wt}" grep -nE '^(<<<<<<< .+|>>>>>>> .+)$' -- . \ + ':!Documentation' > "${EVIDENCE}/source-conflict-markers.txt"; then + cat "${EVIDENCE}/source-conflict-markers.txt" >&2 + exit 1 +fi + +export GIT_AUTHOR_DATE='2026-07-31T14:30:00Z' +export GIT_COMMITTER_DATE='2026-07-31T14:30:00Z' +git -C "${merge_wt}" commit \ + -m 'Merge complete Linux 4.14.287 after boot-confirmed 4.14.283 diagnostic' +source_sha="$(git -C "${merge_wt}" rev-parse HEAD)" +source_tree="$(git -C "${merge_wt}" rev-parse HEAD^{tree})" + +test "$(git -C "${merge_wt}" rev-parse HEAD^1)" = "${SCAFFOLD_283_SHA}" +test "$(git -C "${merge_wt}" rev-parse HEAD^2)" = "${STABLE_287_SHA}" +git -C "${merge_wt}" merge-base --is-ancestor "${PRODUCTION_SHA}" HEAD +git -C "${merge_wt}" merge-base --is-ancestor "${STABLE_287_SHA}" HEAD +! git -C "${merge_wt}" merge-base --is-ancestor "${FDT_292_SHA}" HEAD + +git -C "${merge_wt}" diff-tree --no-commit-id --name-only -r \ + "${SCAFFOLD_283_SHA}" HEAD | sort -u \ + > "${EVIDENCE}/source-delta-from-283.txt" + +{ + echo result=PASS + echo "trigger_sha=${trigger_sha}" + echo "production_sha=${PRODUCTION_SHA}" + echo "source_283_scaffold=${SCAFFOLD_283_SHA}" + echo "audited_source_291=${SOURCE_291_SHA}" + echo "stable_287=${STABLE_287_SHA}" + echo "stable_291=${STABLE_291_SHA}" + echo "excluded_fdt_292=${FDT_292_SHA}" + echo "source_287_sha=${source_sha}" + echo "source_287_tree=${source_tree}" + echo "merge_conflict_count=$(wc -l < "${EVIDENCE}/miru-287-conflicts.txt")" + echo "post_287_stable_path_count=$(wc -l < "${EVIDENCE}/post-287-stable-paths.txt")" + echo "fdt_blob=$(git -C "${merge_wt}" hash-object drivers/of/fdt.c)" + echo "vsprintf_blob=$(git -C "${merge_wt}" hash-object lib/vsprintf.c)" + echo "chacha_header_blob=$(git -C "${merge_wt}" hash-object include/crypto/chacha.h)" + echo "xhci_c_blob=$(git -C "${merge_wt}" hash-object drivers/usb/host/xhci.c)" + echo "xhci_h_blob=$(git -C "${merge_wt}" hash-object drivers/usb/host/xhci.h)" + echo "tcp_output_blob=$(git -C "${merge_wt}" hash-object net/ipv4/tcp_output.c)" + echo raw_extcon_blob=$(git -C "${merge_wt}" hash-object drivers/extcon/extcon.c) + echo early_random_blob=$(git -C "${merge_wt}" hash-object drivers/soc/qcom/early_random.c) +} | tee "${EVIDENCE}/SUMMARY.txt" +sha256sum "${EVIDENCE}"/* > "${EVIDENCE}/SHA256SUMS" + +git -C "${merge_wt}" push origin "HEAD:refs/heads/${TARGET_BRANCH}" +test "$(git ls-remote origin "refs/heads/${TARGET_BRANCH}" | awk '{print $1}')" = "${source_sha}" diff --git a/scripts/miru/materialize_4.14.287_diag26_candidate.sh b/scripts/miru/materialize_4.14.287_diag26_candidate.sh new file mode 100644 index 000000000000..eae5f940acfc --- /dev/null +++ b/scripts/miru/materialize_4.14.287_diag26_candidate.sh @@ -0,0 +1,135 @@ +#!/usr/bin/env bash +set -Eeuo pipefail +set -x + +: "${PRODUCTION_SHA:?}" +: "${SOURCE_SHA:?}" +: "${SOURCE_BRANCH:?}" +: "${STABLE_287_SHA:?}" +: "${DIAG25_HEAD:?}" +: "${TARGET_BRANCH:?}" +: "${FIXED_EXTCON_BLOB:?}" +: "${EARLY_RANDOM_BLOB:?}" + +EVIDENCE="${GITHUB_WORKSPACE}/candidate-287-evidence" +mkdir -p "${EVIDENCE}" +trigger_sha="$(git rev-parse HEAD)" + +test "$(git ls-remote origin refs/heads/miru-h40 | awk '{print $1}')" = "${PRODUCTION_SHA}" +test "$(git ls-remote origin "refs/heads/${SOURCE_BRANCH}" | awk '{print $1}')" = "${SOURCE_SHA}" +test -z "$(git ls-remote origin "refs/heads/${TARGET_BRANCH}")" + +git fetch --no-tags origin "${PRODUCTION_SHA}" "${SOURCE_SHA}" "${DIAG25_HEAD}" +if ! git remote get-url android-common >/dev/null 2>&1; then + git remote add android-common https://github.com/aosp-mirror/kernel_common.git +fi +git fetch --no-tags android-common "${STABLE_287_SHA}" + +test "$(git rev-parse "${SOURCE_SHA}^1")" = b581c659db87713eb2df1c29e4f28e337e5e908c +test "$(git rev-parse "${SOURCE_SHA}^2")" = "${STABLE_287_SHA}" +test "$(git show "${SOURCE_SHA}:Makefile" | sed -n 's/^SUBLEVEL = //p' | head -n1)" = 287 + +test "$(git show "${SOURCE_SHA}:drivers/extcon/extcon.c" | git hash-object --stdin)" = 117da8393690b281f87680bc4ea81b3984f1c24c +test "$(git show "${SOURCE_SHA}:drivers/soc/qcom/early_random.c" | git hash-object --stdin)" = 73fd17290964803ccfd2784cf27ec718ff3de23a +test "$(git show "${SOURCE_SHA}:lib/vsprintf.c" | git hash-object --stdin)" = ad1d198627f1c31e0e3135de8f2320a605a58a3f +test "$(git show "${SOURCE_SHA}:include/crypto/chacha.h" | git hash-object --stdin)" = 84a04c0845a4b0d14469583b1a7f4f62a3fd157d +test "$(git show "${SOURCE_SHA}:drivers/of/fdt.c" | git hash-object --stdin)" = 5e96a55f73b725d0aaf17c1343d380b723238645 +test "$(git show "${SOURCE_SHA}:drivers/usb/host/xhci.c" | git hash-object --stdin)" = cc4b2d066f8180463562b9055a918c4a1c4fdd22 +test "$(git show "${SOURCE_SHA}:drivers/usb/host/xhci.h" | git hash-object --stdin)" = 4e3554115e1b0aa804d0d36d14b8121d537f5570 +test "$(git show "${SOURCE_SHA}:net/ipv4/tcp_output.c" | git hash-object --stdin)" = 4edb8f630035f2b1f12ecf498d13b6953573056c + +test "$(git show "${DIAG25_HEAD}:drivers/extcon/extcon.c" | git hash-object --stdin)" = "${FIXED_EXTCON_BLOB}" +test "$(git show "${DIAG25_HEAD}:drivers/soc/qcom/early_random.c" | git hash-object --stdin)" = "${EARLY_RANDOM_BLOB}" + +wt="${RUNNER_TEMP}/miru-287-diag26-candidate" +rm -rf "${wt}" +git worktree add --detach "${wt}" "${SOURCE_SHA}" +git -C "${wt}" config user.name github-actions[bot] +git -C "${wt}" config user.email 41898282+github-actions[bot]@users.noreply.github.com + +git show "${DIAG25_HEAD}:drivers/extcon/extcon.c" > "${wt}/drivers/extcon/extcon.c" +git show "${DIAG25_HEAD}:drivers/soc/qcom/early_random.c" > "${wt}/drivers/soc/qcom/early_random.c" +git show "${DIAG25_HEAD}:.github/workflows/miru-h40-build.yml" > "${wt}/.github/workflows/miru-h40-build.yml" + +python3 - "${wt}/.github/workflows/miru-h40-build.yml" <<'PY' +from pathlib import Path +import sys +p = Path(sys.argv[1]) +s = p.read_text() +repls = [ + ('a79859d15ae0025897791a77654bcebeedc708ab', '705dd8a9d1e74a896a28d1a3efd6ff30fcc4e3b4'), + ('e548869f356fead9fdcb3562f52d2226574f4f41', '1048779a1d7dcf0b5c150188decafa21c19821e4'), + ('STABLE_291_SHA', 'STABLE_287_SHA'), + ('miru-h40-lts291-source-diag25', 'miru-h40-lts287-source-diag26'), + ('4.14.291', '4.14.287'), + ('full291', 'full287'), + ('diag25', 'diag26'), +] +for old, new in repls: + count = s.count(old) + if count < 1: + raise SystemExit(f'missing workflow token: {old}') + s = s.replace(old, new) +for stale in ('a79859d15ae0025897791a77654bcebeedc708ab', + 'e548869f356fead9fdcb3562f52d2226574f4f41', + 'STABLE_291_SHA', 'miru-h40-lts291-source-diag25', + '4.14.291', 'full291', 'diag25'): + if stale in s: + raise SystemExit(f'stale workflow token remains: {stale}') +required = ( + 'SOURCE_SHA: 705dd8a9d1e74a896a28d1a3efd6ff30fcc4e3b4', + 'STABLE_287_SHA: 1048779a1d7dcf0b5c150188decafa21c19821e4', + 'EXPECTED_RELEASE: 4.14.287-miru-h40-diag26-full287-extconfix+', + 'miru-h40-4.14.287-diag26-full287-extconfix-kernel.zip', + 'export KERNEL_LOCALVERSION=-miru-h40-diag26-full287-extconfix', +) +for token in required: + if token not in s: + raise SystemExit(f'required workflow token missing: {token}') +p.write_text(s) +PY + +git -C "${wt}" add -- .github/workflows/miru-h40-build.yml drivers/extcon/extcon.c drivers/soc/qcom/early_random.c +test -z "$(git -C "${wt}" ls-files -u)" +git -C "${wt}" diff --check --cached + +git -C "${wt}" diff --name-only --cached | sort -u > "${EVIDENCE}/candidate-delta.txt" +printf '%s\n' \ + .github/workflows/miru-h40-build.yml \ + drivers/extcon/extcon.c \ + drivers/soc/qcom/early_random.c \ + > "${EVIDENCE}/expected-candidate-delta.txt" +cmp -s "${EVIDENCE}/expected-candidate-delta.txt" "${EVIDENCE}/candidate-delta.txt" + +test "$(git -C "${wt}" hash-object drivers/extcon/extcon.c)" = "${FIXED_EXTCON_BLOB}" +test "$(git -C "${wt}" hash-object drivers/soc/qcom/early_random.c)" = "${EARLY_RANDOM_BLOB}" +grep -Fq '#include ' "${wt}/drivers/soc/qcom/early_random.c" +grep -Fq 'edev->bnh = kcalloc(edev->max_supported, sizeof(*edev->bnh)' "${wt}/drivers/extcon/extcon.c" +grep -Fq 'EXPECTED_RELEASE: 4.14.287-miru-h40-diag26-full287-extconfix+' "${wt}/.github/workflows/miru-h40-build.yml" + +export GIT_AUTHOR_DATE='2026-07-31T15:10:00Z' +export GIT_COMMITTER_DATE='2026-07-31T15:10:00Z' +git -C "${wt}" commit -m 'diag: build Linux 4.14.287 midpoint kernel only' +candidate_sha="$(git -C "${wt}" rev-parse HEAD)" +candidate_tree="$(git -C "${wt}" rev-parse HEAD^{tree})" +test "$(git -C "${wt}" rev-parse HEAD^1)" = "${SOURCE_SHA}" +git -C "${wt}" merge-base --is-ancestor "${PRODUCTION_SHA}" HEAD +git -C "${wt}" merge-base --is-ancestor "${STABLE_287_SHA}" HEAD + +{ + echo result=PASS + echo "trigger_sha=${trigger_sha}" + echo "production_sha=${PRODUCTION_SHA}" + echo "source_sha=${SOURCE_SHA}" + echo "stable_287=${STABLE_287_SHA}" + echo "diag25_reference=${DIAG25_HEAD}" + echo "candidate_sha=${candidate_sha}" + echo "candidate_tree=${candidate_tree}" + echo "fixed_extcon_blob=${FIXED_EXTCON_BLOB}" + echo "early_random_blob=${EARLY_RANDOM_BLOB}" + echo candidate_delta_files=3 +} | tee "${EVIDENCE}/SUMMARY.txt" +sha256sum "${EVIDENCE}"/* > "${EVIDENCE}/SHA256SUMS" + +git -C "${wt}" push origin "HEAD:refs/heads/${TARGET_BRANCH}" +test "$(git ls-remote origin "refs/heads/${TARGET_BRANCH}" | awk '{print $1}')" = "${candidate_sha}" diff --git a/scripts/miru/materialize_4.14.291_diag21.sh b/scripts/miru/materialize_4.14.291_diag21.sh new file mode 100644 index 000000000000..66d988f9caec --- /dev/null +++ b/scripts/miru/materialize_4.14.291_diag21.sh @@ -0,0 +1,267 @@ +#!/usr/bin/env bash +set -Eeuo pipefail +set -x + +: "${PRODUCTION_SHA:?}" +: "${SCAFFOLD_283_SHA:?}" +: "${COMMON_283_SHA:?}" +: "${GOOD_FIRST_PARENT_SHA:?}" +: "${COMMON_305_MERGE_SHA:?}" +: "${DIRECT_305_REFERENCE_SHA:?}" +: "${STABLE_291_SHA:?}" +: "${STABLE_305_SHA:?}" +: "${FDT_292_SHA:?}" +: "${TARGET_BRANCH:?}" + +EVIDENCE="${GITHUB_WORKSPACE}/source-generation-evidence" +mkdir -p "${EVIDENCE}" +trigger_sha="$(git rev-parse HEAD)" + +test "$(git ls-remote origin refs/heads/miru-h40 | awk '{print $1}')" = "${PRODUCTION_SHA}" +test -z "$(git ls-remote origin "refs/heads/${TARGET_BRANCH}")" + +git fetch --no-tags origin \ + "${PRODUCTION_SHA}" "${SCAFFOLD_283_SHA}" "${COMMON_283_SHA}" \ + "${GOOD_FIRST_PARENT_SHA}" "${COMMON_305_MERGE_SHA}" \ + "${DIRECT_305_REFERENCE_SHA}" +if ! git remote get-url android-common >/dev/null 2>&1; then + git remote add android-common https://github.com/aosp-mirror/kernel_common.git +fi +git fetch --no-tags android-common \ + "${STABLE_291_SHA}" "${STABLE_305_SHA}" "${FDT_292_SHA}" + +# Immutable provenance and pre-FDT boundary gates. +test "$(git rev-parse "${SCAFFOLD_283_SHA}^1")" = "${PRODUCTION_SHA}" +test "$(git rev-parse "${SCAFFOLD_283_SHA}^2")" = "${COMMON_283_SHA}" +test "$(git rev-parse "${COMMON_305_MERGE_SHA}^2")" = "${STABLE_305_SHA}" +git merge-base --is-ancestor "${PRODUCTION_SHA}" "${SCAFFOLD_283_SHA}" +git merge-base --is-ancestor "${COMMON_305_MERGE_SHA}" "${DIRECT_305_REFERENCE_SHA}" +git merge-base --is-ancestor "${STABLE_291_SHA}" "${STABLE_305_SHA}" +git merge-base --is-ancestor "${STABLE_291_SHA}" "${FDT_292_SHA}" +! git merge-base --is-ancestor "${FDT_292_SHA}" "${STABLE_291_SHA}" +test "$(git show -s --format=%s "${STABLE_291_SHA}")" = 'Linux 4.14.291' +test "$(git show "${STABLE_291_SHA}:Makefile" | sed -n 's/^SUBLEVEL = //p' | head -n1)" = 291 +test "$(git rev-list --count "${STABLE_291_SHA}" --not b8f3be299d5176348b15cc59d55b85faa3dece68)" = 874 + +common_wt="${RUNNER_TEMP}/common-291" +common_ref_wt="${RUNNER_TEMP}/common-305-downgraded" +direct_ref_wt="${RUNNER_TEMP}/miru-305-downgraded" +source_wt="${RUNNER_TEMP}/miru-291" +rm -rf "${common_wt}" "${common_ref_wt}" "${direct_ref_wt}" "${source_wt}" + +# Reconstruct the exact Android Common 4.14.291 semantic merge. +git worktree add --detach "${common_wt}" "${GOOD_FIRST_PARENT_SHA}" +git -C "${common_wt}" config user.name github-actions[bot] +git -C "${common_wt}" config user.email 41898282+github-actions[bot]@users.noreply.github.com +set +e +git -C "${common_wt}" merge --no-commit --no-ff "${STABLE_291_SHA}" \ + > "${EVIDENCE}/common-291-merge.log" 2>&1 +common_rc=$? +set -e +test "${common_rc}" = 1 +git -C "${common_wt}" diff --name-only --diff-filter=U | sort -u \ + > "${EVIDENCE}/common-291-conflicts.txt" +cat > "${EVIDENCE}/expected-common-291-conflicts.txt" <<'EOF' +crypto/chacha20_generic.c +drivers/char/random.c +drivers/nfc/st21nfca/se.c +drivers/of/fdt.c +fs/ext4/namei.c +include/crypto/chacha20.h +lib/chacha20.c +EOF +diff -u "${EVIDENCE}/expected-common-291-conflicts.txt" \ + "${EVIDENCE}/common-291-conflicts.txt" +mapfile -t common_conflicts < "${EVIDENCE}/common-291-conflicts.txt" + +git worktree add --detach "${common_ref_wt}" "${COMMON_305_MERGE_SHA}" +git diff --binary --full-index "${STABLE_305_SHA}" "${STABLE_291_SHA}" -- \ + "${common_conflicts[@]}" > "${EVIDENCE}/common-305-to-291.patch" +sha256sum "${EVIDENCE}/common-305-to-291.patch" \ + > "${EVIDENCE}/common-305-to-291.patch.sha256" +git -C "${common_ref_wt}" apply --3way --index \ + "${EVIDENCE}/common-305-to-291.patch" \ + > "${EVIDENCE}/common-downgrade-apply.log" 2>&1 +test -z "$(git -C "${common_ref_wt}" diff --name-only --diff-filter=U)" +test -z "$(git -C "${common_ref_wt}" ls-files -u)" + +for rel in "${common_conflicts[@]}"; do + if [ -e "${common_ref_wt}/${rel}" ] || [ -L "${common_ref_wt}/${rel}" ]; then + mkdir -p "$(dirname "${common_wt}/${rel}")" + rm -rf "${common_wt:?}/${rel}" + cp -a "${common_ref_wt}/${rel}" "${common_wt}/${rel}" + git -C "${common_wt}" add -- "${rel}" + else + git -C "${common_wt}" rm -f --ignore-unmatch -- "${rel}" + fi +done +test -z "$(git -C "${common_wt}" ls-files -u)" +test "$(sed -n 's/^SUBLEVEL = //p' "${common_wt}/Makefile" | head -n1)" = 291 +export GIT_AUTHOR_DATE='2026-07-31T07:50:00Z' +export GIT_COMMITTER_DATE='2026-07-31T07:50:00Z' +git -C "${common_wt}" commit -m 'Merge Linux 4.14.291 stable endpoint for Miru diagnostic' +common_291_sha="$(git -C "${common_wt}" rev-parse HEAD)" +test "$(git -C "${common_wt}" rev-parse 'HEAD^1')" = "${GOOD_FIRST_PARENT_SHA}" +test "$(git -C "${common_wt}" rev-parse 'HEAD^2')" = "${STABLE_291_SHA}" + +# Downgrade the audited Miru 4.14.305 conflict-resolution files to 4.14.291. +miru_nodrift_paths=(drivers/char/Kconfig lib/Makefile) +miru_drift_paths=(drivers/usb/host/xhci.c drivers/usb/host/xhci.h net/ipv4/tcp_output.c) +miru_paths=("${miru_nodrift_paths[@]}" "${miru_drift_paths[@]}") +git diff --name-only "${STABLE_291_SHA}" "${STABLE_305_SHA}" -- \ + "${miru_nodrift_paths[@]}" > "${EVIDENCE}/post-291-nodrift-check.txt" +test ! -s "${EVIDENCE}/post-291-nodrift-check.txt" +git diff --name-only "${STABLE_291_SHA}" "${STABLE_305_SHA}" -- \ + "${miru_drift_paths[@]}" | sort -u > "${EVIDENCE}/post-291-miru-drift.txt" +cat > "${EVIDENCE}/expected-post-291-miru-drift.txt" <<'EOF' +drivers/usb/host/xhci.c +drivers/usb/host/xhci.h +net/ipv4/tcp_output.c +EOF +diff -u "${EVIDENCE}/expected-post-291-miru-drift.txt" \ + "${EVIDENCE}/post-291-miru-drift.txt" + +git worktree add --detach "${direct_ref_wt}" "${DIRECT_305_REFERENCE_SHA}" +git diff --binary --full-index "${STABLE_305_SHA}" "${STABLE_291_SHA}" -- \ + "${miru_drift_paths[@]}" > "${EVIDENCE}/miru-305-to-291.patch" +sha256sum "${EVIDENCE}/miru-305-to-291.patch" \ + > "${EVIDENCE}/miru-305-to-291.patch.sha256" +set +e +git -C "${direct_ref_wt}" apply --3way --index \ + "${EVIDENCE}/miru-305-to-291.patch" \ + > "${EVIDENCE}/miru-downgrade-apply.log" 2>&1 +miru_downgrade_rc=$? +set -e +test "${miru_downgrade_rc}" = 1 +git -C "${direct_ref_wt}" diff --name-only --diff-filter=U | sort -u \ + > "${EVIDENCE}/miru-downgrade-conflicts.txt" +printf '%s\n' drivers/usb/host/xhci.h \ + > "${EVIDENCE}/expected-miru-downgrade-conflicts.txt" +diff -u "${EVIDENCE}/expected-miru-downgrade-conflicts.txt" \ + "${EVIDENCE}/miru-downgrade-conflicts.txt" + +# Exact semantic resolution: stable 4.14.292+ added run_graceperiod. Remove only +# that field while retaining the audited Miru xHCI extensions and layout. +git -C "${direct_ref_wt}" checkout --ours -- drivers/usb/host/xhci.h +python3 - "${direct_ref_wt}/drivers/usb/host/xhci.h" <<'PY' +from pathlib import Path +import sys +path = Path(sys.argv[1]) +text = path.read_text() +needle = "\tunsigned long\t\trun_graceperiod;\n" +if text.count(needle) != 1: + raise SystemExit(f"expected exactly one run_graceperiod field, found {text.count(needle)}") +path.write_text(text.replace(needle, "", 1)) +PY +git -C "${direct_ref_wt}" add -- drivers/usb/host/xhci.h +test -z "$(git -C "${direct_ref_wt}" diff --name-only --diff-filter=U)" +test -z "$(git -C "${direct_ref_wt}" ls-files -u)" +! grep -Fq 'run_graceperiod' "${direct_ref_wt}/drivers/usb/host/xhci.h" +! grep -Fq 'run_graceperiod' "${direct_ref_wt}/drivers/usb/host/xhci.c" + +# Merge the stable endpoint into the proven physical 4.14.283 scaffold. +git worktree add --detach "${source_wt}" "${SCAFFOLD_283_SHA}" +git -C "${source_wt}" config user.name github-actions[bot] +git -C "${source_wt}" config user.email 41898282+github-actions[bot]@users.noreply.github.com +set +e +git -C "${source_wt}" merge --no-commit --no-ff "${STABLE_291_SHA}" \ + > "${EVIDENCE}/miru-283-to-291-merge.log" 2>&1 +source_rc=$? +set -e +test "${source_rc}" = 1 +git -C "${source_wt}" diff --name-only --diff-filter=U | sort -u \ + > "${EVIDENCE}/miru-291-conflicts.txt" +cat > "${EVIDENCE}/expected-miru-291-conflicts.txt" <<'EOF' +crypto/chacha20_generic.c +drivers/char/Kconfig +drivers/char/random.c +drivers/of/fdt.c +drivers/usb/host/xhci.c +drivers/usb/host/xhci.h +fs/ext4/namei.c +include/crypto/chacha20.h +lib/Makefile +lib/chacha20.c +net/ipv4/tcp_output.c +EOF +diff -u "${EVIDENCE}/expected-miru-291-conflicts.txt" \ + "${EVIDENCE}/miru-291-conflicts.txt" + +for rel in crypto/chacha20_generic.c include/crypto/chacha20.h lib/chacha20.c; do + git -C "${source_wt}" rm -f --ignore-unmatch -- "${rel}" +done +for rel in drivers/char/random.c drivers/of/fdt.c fs/ext4/namei.c; do + mkdir -p "$(dirname "${source_wt}/${rel}")" + rm -rf "${source_wt:?}/${rel}" + cp -a "${common_wt}/${rel}" "${source_wt}/${rel}" + git -C "${source_wt}" add -- "${rel}" + test "$(git -C "${source_wt}" hash-object "${rel}")" = \ + "$(git -C "${common_wt}" hash-object "${rel}")" +done +for rel in "${miru_paths[@]}"; do + mkdir -p "$(dirname "${source_wt}/${rel}")" + rm -rf "${source_wt:?}/${rel}" + cp -a "${direct_ref_wt}/${rel}" "${source_wt}/${rel}" + git -C "${source_wt}" add -- "${rel}" + test "$(git -C "${source_wt}" hash-object "${rel}")" = \ + "$(git -C "${direct_ref_wt}" hash-object "${rel}")" +done + +test -z "$(git -C "${source_wt}" diff --name-only --diff-filter=U)" +test -z "$(git -C "${source_wt}" ls-files -u)" +git -C "${source_wt}" diff --check +test "$(sed -n 's/^SUBLEVEL = //p' "${source_wt}/Makefile" | head -n1)" = 291 +test "$(git -C "${source_wt}" hash-object drivers/extcon/extcon.c)" = \ + 117da8393690b281f87680bc4ea81b3984f1c24c +! grep -Fq '#include ' "${source_wt}/drivers/soc/qcom/early_random.c" +grep -Fq 'void *dt_virt = fixmap_remap_fdt(dt_phys);' \ + "${source_wt}/arch/arm64/kernel/setup.c" +! grep -Fq 'fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL)' \ + "${source_wt}/arch/arm64/kernel/setup.c" +if git -C "${source_wt}" grep -nE '^(<<<<<<< .+|>>>>>>> .+)$' -- . \ + ':!Documentation' > "${EVIDENCE}/source-conflict-markers.txt"; then + cat "${EVIDENCE}/source-conflict-markers.txt" >&2 + exit 1 +fi + +export GIT_AUTHOR_DATE='2026-07-31T08:20:00Z' +export GIT_COMMITTER_DATE='2026-07-31T08:20:00Z' +git -C "${source_wt}" commit \ + -m 'Merge complete Linux 4.14.291 after proven 4.14.283 diagnostic' +source_sha="$(git -C "${source_wt}" rev-parse HEAD)" +source_tree="$(git -C "${source_wt}" rev-parse 'HEAD^{tree}')" +test "$(git -C "${source_wt}" rev-parse 'HEAD^1')" = "${SCAFFOLD_283_SHA}" +test "$(git -C "${source_wt}" rev-parse 'HEAD^2')" = "${STABLE_291_SHA}" +git -C "${source_wt}" merge-base --is-ancestor "${PRODUCTION_SHA}" HEAD +git -C "${source_wt}" merge-base --is-ancestor "${STABLE_291_SHA}" HEAD +! git -C "${source_wt}" merge-base --is-ancestor "${FDT_292_SHA}" HEAD + +git -C "${source_wt}" ls-tree -r HEAD > "${EVIDENCE}/final-source-tree.txt" +git -C "${source_wt}" diff --stat "${SCAFFOLD_283_SHA}" HEAD \ + > "${EVIDENCE}/scaffold-to-source.stat" +{ + echo result=PASS + echo "trigger_sha=${trigger_sha}" + echo "production_sha=${PRODUCTION_SHA}" + echo "proven_283_scaffold=${SCAFFOLD_283_SHA}" + echo "stable_291_sha=${STABLE_291_SHA}" + echo "excluded_fdt_292_sha=${FDT_292_SHA}" + echo "common_291_merge_sha=${common_291_sha}" + echo "source_sha=${source_sha}" + echo "source_tree=${source_tree}" + echo source_sublevel=291 + echo source_extcon_blob=117da8393690b281f87680bc4ea81b3984f1c24c + echo early_random_include=absent_requires_compatibility_repair + echo unresolved_conflicts=0 + echo miru_conflict_count=11 + echo common_conflict_count=7 + echo post_291_miru_drift_count=3 + echo xhci_header_resolution=remove_only_run_graceperiod +} | tee "${EVIDENCE}/SOURCE-SUMMARY.txt" +find "${EVIDENCE}" -maxdepth 1 -type f ! -name SHA256SUMS.txt -print0 \ + | sort -z | xargs -0 sha256sum > "${EVIDENCE}/SHA256SUMS.txt" + +test "$(git ls-remote origin refs/heads/miru-h40 | awk '{print $1}')" = "${PRODUCTION_SHA}" +test -z "$(git ls-remote origin "refs/heads/${TARGET_BRANCH}")" +git -C "${source_wt}" push origin "${source_sha}:refs/heads/${TARGET_BRANCH}" +test "$(git ls-remote origin "refs/heads/${TARGET_BRANCH}" | awk '{print $1}')" = "${source_sha}"