Communitygithub.com

linux-phone-porting

메인라인 리눅스를 안드로이드(?) 폰에 포팅하는 과정을 안내하는 AI 에이전트 스킬입니다.

linux-phone-porting란 무엇인가요?

이 스킬은 안드로이드 폰에 메인라인 리눅스 커널을 포팅하는 과정을 체계적으로 안내합니다. 포팅 작업은 일반적으로 디버그 주기가 매우 길고(빌드-플래시-부팅에 5~10분 소요), 맹목적인 수정이 실패하는 경우가 많습니다. 따라서 이 스킬은 백업, 증거 수집, 연구, 구현이라는 4단계의 엄격한 순서를 따르도록 설계되었습니다. 1단계(0단계)에서는 대상 기기의 정확한 식별(마케팅명, 코드명, SoC, 변형 모델), 부트로더 상태, 타겟 배포판을 확인하고, 사용자 데이터를 제외한 모든 파티션을 백업합니다. 이 과정에서 스톡 DTB, 펌웨어 블롭, 커널 cmdline 등 포팅에 필수적인 참조 자료를 확보합니다. 2단계(1단계)에서는 고장난 부팅의 전체 dmesg를 캡처하고, pstore, ramoops, USB ACM 콘솔 등 다양한 채널을 통해 충돌 증거를 수집합니다. 또한 측정 중 발생할 수 있는 오류(예: 디버그 인터페이스 읽기로 인한 증상 유발, errno 오해석)를 방지하는 5가지 규칙을 제공합니다. 3단계(2단계)에서는 메인라인, 다운스트림 OEM 커널 소스, postmarketOS, Halium/UBports, Mobian, NixOS 등 6가지 소스군을 병렬로 조사하여 문제의 원인이나 필요한 드라이버를 파악합니다. 결과가 빈 경우는 일반적인 상황이며, 그때는 스톡 DTB나 OEM 드라이버 등의 1차 자료에서 답을 찾습니다. 4단계(3단계)에서는 하나의 변경 사항만 포함하는 커널을 빌드하고 플래시하여 단일 변수 테스트를 수행합니다. 빌드, 플래시, 부팅의 각 단계에서 실패 시 이전 단계로 롤백하여 원인을 좁혀 나갑니다. 변경 사항이 차례로 쌓여 기기가 부팅되면 결과를 기록하고 주기적으로 통합합니다. 이 스킬은 Claude Code, Cursor, Codex 등 다양한 AI 에이전트 플랫폼에서 사용할 수 있도록 설계되었으며, SKILL.md 문서에 상세한 지침이 포함되어 있습니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add angelwzr/linux-phone-porting

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Linux Phone Porting

메인라인 부트업 중인 폰에서 디버그 한 주기는 빌드 + 플래시 + 부팅(5~10분)이 소요되며, 블라인드 수정은 성공보다 훨씬 자주 반증됩니다. 다음 순서를 엄격히 따르십시오.

0. 포트 설정

이 작업은 첫 플래시 전에 한 번만 수행합니다. 두 가지 이유로 이것을 서류 작업이 아닌 0단계로 삼습니다: 스톡 시스템은 이 보드에 대해 언제나 얻을 수 있는 가장 권위 있는 연구 자료이며, 파티션을 덮어쓰기 시작하는 순간 그 일부를 읽을 수 없게 됩니다.

모든 후속 답변이 이에 의존하므로 먼저 대상을 확립하십시오:

  • 정확한 기기 식별 — 마케팅명, 코드명, SoC, 지역 또는 저장소 변형. 동일 마케팅명의 형제 변형은 패널, 터치 컨트롤러 또는 모뎀이 자주 다르며, 잘못된 변형에 대해 조사된 수정은 그럴듯해 보이지만 실패합니다.
  • 타겟 배포판 및 init — postmarketOS, Mobian, NixOS, 일반 데비안 또는 기타. 이는 패키징, 이미지 레이아웃, 그리고 2단계 소스 중 어느 것이 가장 가까운지를 결정합니다.
  • 부트 토폴로지 — A/B 또는 비A/B, 슬롯 레이아웃, 부트로더 잠금 상태. 잠금 해제된 부트로더만 허용합니다. 부트로더가 잠겨 있으면 중단하십시오: 이 스킬은 부트로더를 잠금 해제하지 않으며 잠금 해제 단계를 제공하지 않습니다 — 사용자를 해당 OEM의 지침으로 안내하고 기기가 잠금 해제된 후에 재개하십시오.
  • 복구 — 커스텀 복구 설치 여부. 필수 사항은 아닙니다: 백업 및 복원을 위한 편의 사항입니다.

그런 다음 userdata를 제외한 모든 파티션의 전체 백업을 수행하십시오:

  • userdata 건너뛰기: 대부분의 공간을 차지하며 사용자 데이터이고, 잃어도 감당할 수 있는 유일한 파티션입니다.
  • 기기 고유 파티션을 백업하고 절대 공개하지 마십시오. 모뎀 NV/EFS, persist 및 해당 보정 파티션은 이 개별 핸드셋의 IMEI, 무선 보정 및 센서 트림을 담고 있습니다. 인터넷의 어떤 이미지로도 재현할 수 없으며, 이를 손상시키는 포트는 네트워크에 등록할 수 없는 폰을 남깁니다. 중요하고 비공개로 취급하십시오.
  • 모든 이미지를 해시하고 파티션 테이블과 함께 해시를 기록하십시오. 나중에 "기기에 있는 것이 내가 백업한 것과 같은가"라는 질문에 답해야 하며, 오직 해시만이 답을 줍니다.
  • 첫 번째 위험한 플래시 전에(이후가 아닌) 백업이 실제로 복원 가능한지 확인하십시오.

백업이 복구 외에도 연구로서 가지는 가치:

  • 스톡 DTB — 이 보드의 디바이스 트리에 대한 근본 진실이며, 형제 SoC의 dtsi가 이와 일치하지 않을 때의 결정자입니다.
  • 펌웨어 블롭 및 로드 순서 — 벤더 스택이 실제로 제공하는 것과それが 예상하는 위치.
  • 벤더 커널 cmdline 및 부트 이미지 레이아웃 — 오프셋, 헤더 버전, 스톡 커널에 제공된 인수.
  • 정확한 커널 버전 문자열 — 스톡 ROM의 uname -a 또는 /proc/version (읽을 수 있는 동안; 나중에 백업된 부트 이미지에서도 추출 가능). 이는 2단계에서 올바른 GPL 게시 OEM 소스 릴리즈를 선택하는 지문입니다. 벤더는 여러 빌드를 제공하며 이들은 다릅니다.
  • 벤더 구성 — 메인라인 드라이버가 충족해야 하는 인터페이스를 설명하는 센서, 모뎀 및 HAL 구성.

마지막으로, 세션의 나머지 부분에서 가정하는 작업 규칙을 설정하십시오: 부팅당 하나의 하위 디렉토리를 로그와 pstore용으로 축적하는 호스트 측 디렉토리, 그리고 작동하는 것으로 알려진 복구 경로에 대한 메모. 이전 시도의 백업이 이미 존재하는 경우, 이러한 파티션을 포함하고 해시가 여전히 검증되는지 확인하십시오(가정하지 마십시오).

1. 라이브 기기에서 먼저 증거 수집

무엇이든 변경하기 전에 실패한 실행의 전체 dmesg를 캡처하십시오. 재현 전에 관련 디버그 노브를 활성화하십시오(예: echo 0xffffffff > /sys/module/<driver>/parameters/debug_mask). 두 번째 재현은 또 다른 부팅을 소모하기 때문입니다.

증거 채널, 신뢰성 순서:

  • 네트워크 또는 USB를 통한 라이브 셸. 가장 저렴한 채널; 기기가 살아있는 모든 것에 사용하십시오.
  • pstore. systemd가 실행 중이면 /var/lib/systemd/pstore/에서 수집하고, /sys/fs/pstore/에서 하지 마십시오 — systemd-pstore.service는 부팅 초기에 모든 레코드를 _이동_시키므로, 빈 /sys/fs/pstore는 충돌이 기록되지 않았다는 증거가 아닙니다. 콘솔 영역은 일반적으로 단일 슬롯입니다: 다른 작업을 하기 전에 호스트로 복사하십시오. 그렇지 않으면 다음 충돌이 아카이브에서도 덮어씁니다.
  • ramoops. 손실이 있는 것으로 취급하십시오. DRAM 전하 유지는 전원이 꺼진 간격 동안 감소합니다 — 한 기기에서 비트의 약 6.5%로 측정되었으며, 영역 헤더에서 ECC를 실패시키고 레코드를 완전히 잃을 만큼입니다. 레코드를 _퍼지_하게 grep하십시오. 영역이 손상되는 것은 전원이 꺼진 시간이지, 전원을 끄기 전에 스팸을 보낸 시간이 아니므로, 멈춘 기기가 콘솔 영역이 유지할 수 있는 한 오래 로그를 기록하게 한 다음 전원을 껐다가 즉시 켜십시오. 서두를 필요가 있다고 가정하기 전에 영역 크기를 확인하십시오: 4MiB 콘솔 영역은 래핑되기 전에 몇 시간의 워치독 스팸을 흡수합니다.
  • 커널 수준 USB ACM 콘솔 (CONFIG_U_SERIAL_CONSOLE=y 및 cmdline의 console=ttyGS0). 멈춤을 견디는 유일한 채널이며, 포트 초기에 일회성 플래시 비용을 들일 가치가 있습니다. 사용자 공간 ACM getty는 멈춤을 견디지 못합니다 — 스케줄 가능한 CPU가 필요하며, USB를 통해 여전히 잘 열거되는 동안 0바이트를 생성합니다. 두 부분이 모두 필요합니다: 구성 심볼만으로는 기능이 비활성화 상태입니다.

추론을 측정으로 반복해서 전환시키는 다섯 가지 규칙:

  • 실제로 플래시된 것이 무엇인지 파티션을 읽어서 확인하십시오, 노트나 빌드 로그에서 절대 확인하지 마십시오. iflag=direct로 읽어 읽기 자체가 디버깅 중인 것을 방해하지 않도록 하십시오. 크기만 비교하는 것을 주의하십시오 — 부트 이미지는 고정된 크기로 패딩되므로, 두 개의 다른 이미지에서 동일한 길이는 아무것도 증명하지 않습니다. 페이로드를 해시하십시오.
  • 디버그 인터페이스를 읽으면 증상이 생성될 수 있습니다. DRM/GPU 충돌 상태 노드가 전형적인 예입니다: GPU가 활발히 제출하는 동안 하나를 샘플링하면 발생하지 않은 오류 및 복구 라인을 합성합니다(측정: 다섯 번 읽기, 다섯 개의 오류/복구 쌍, 관찰되지 않은 경우 없음). 로그 라인을 신뢰하기 전에 자신의 관찰이 그것을 생성했는지 확인하십시오.
  • 거부의 원시 응답을 해석된 errno 이전에 캡처하십시오. 펌웨어 호출의 매핑된 오류는 모호했습니다 — EINVAL은 잘못된 인코딩 또는 거부된 정책을 의미할 수 있음 — 콜 래퍼의 동적 디버그가 원시 응답 단어를 노출할 때까지: 명시적인 거부를 수반하는 잘 형성된 호출. 이는 정책이지 인코딩이 아닙니다 — 반대 평결, 반대 다음 단계. 모든 펌웨어 거부를 잘못된 인코딩, 정책에 의한 거부, 또는 찾을 수 없음으로 분류한 후에 조치하십시오. 미러 규칙: 깨끗하고 잘 형성된 부정은 긍정적 증거입니다 — 올바르게 형성된 조회에서 찾을 수 없음은 인코딩을 검증하고 로더를 건드리지 않고 계획의 한 분기를 제거합니다.
  • 제어되지 않은 조건과 경쟁하는 측정은 그럴듯하지만 무효인 숫자를 반환합니다. 한 벤치마크가 2초에 55점을 기록했습니다: 컴포지터가 DRM 마스터를 보유했고, 모든 장면이 실패했으며, 조건이 확인될 때까지 숫자는 실제처럼 보였습니다. 유효한 비교(132 → 485)는 두 실행 모두에 대해 컴포지터를 중지시키고, 해당 세대 내에서만 비교해야 했습니다. 벤치마크를 신뢰하기 전에, 그것을 무효화할 수 있는 조건의 이름을 지정하고 모든 실행에 대해 유지되었는지 확인하십시오.
  • 철회한 규칙을 기록하십시오. 부트업은 민속을 빠르게 축적하며, 하나의 하드웨어 개정 또는 하나의 버퍼 크기에 대해 옳았던 규칙은 변경 후에 적극적으로 오해를 불러일으킵니다. 변경된 사항과 함께 현재 규칙 옆에 뒤집힌 버전을 유지하십시오. 그래야 다음 세션이 어떤 조언이 스트레스 테스트를 거쳤는지 알 수 있습니다.

선제적으로 대비할 가치가 있는 호스트 측 문제점:

  • timeout N ssh <device> '<cmd>'는 로컬 클라이언트만 종료합니다. 원격 프로세스는 계속 실행됩니다. 명시적인 kill로 후속 조치하십시오.
  • pgrep -f 및 pkill -f는 동일한 ssh 경로를 통해 실행될 때 자체 일치하는 원격 셸을 생성합니다. 일치 항목을 필터링하거나 PID로 일치시키십시오.
  • find는 시작 경로가 심볼릭 링크일 때 -L이 필요합니다. 그렇지 않으면 조용히 빈 결과를 반환합니다.
  • 명령 출력을 다시 작성하는 모든 래퍼 또는 후크(토큰 필터, 페이저, 포맷터)는 증거를 손상시키며, 때로는 명백히 깨지는 대신 테스트를 반전시킵니다. 발견 사항으로 커밋할 모든 것에 대해 원시 명령을 사용하십시오.

2. 구현 전 연구 — 모든 소스

연구는 항상 구현에 선행합니다. 소비하는 것은 수행 중인 작업에 따라 다릅니다:

  • 실패 조사 — 1단계 증거. 먼저 캡처하십시오. 실제로 읽지 않은 증상을 연구하는 것은 인용구로 추측하는 것입니다.
  • 기능 추가 — 한 번도 등장한 적 없는 드라이버, 주변 장치, 서브시스템 — 0단계 아티팩트가 기기 데이터입니다. 스톡 DTB, 벤더 구성 및 펌웨어 레이아웃은 이 보드가 어떻게 구동되기를 기대하는지 설명하며, 여기서 충돌 로그만큼 권위적입니다.

어느 쪽이든, 무엇이든 작성하기 전에:

  1. 서브시스템에 대해 추론하십시오 — 실패를 소유하거나 새 기능을 소유할 드라이버, 바인딩 또는 펌웨어 인터페이스를 식별하십시오. 세션 컨텍스트에서 사용할 수 있는 스킬이 나열되어 있습니다. 지금 해당 목록을 스캔하고 커널 개발 또는 충돌 분석 스킬이 있으면 계속하기 전에 읽으십시오 — 레지스터 수준 및 바인딩 세부 정보가 이 단계에 정확히 필요한 것입니다. 나열된 것이 없을 때만 직접 추론하십시오.
  2. 관련된 사용자 공간 라이브러리 및 도구를 조회하십시오 — 기억된 API가 아닌 최신 문서. 동일한 세션 목록에 문서 검색 스킬이 있으면 메모리에서 서명을 불러오는 대신 실행하십시오.
  3. 여섯 가지 소스군 모두에 대한 웹 연구 (병렬 하위 에이전트가 여기서 잘 작동합니다. 목록에 웹 연구 스킬이 있으면 캐싱을 위해 선호하십시오. 세션이 동일한 페이지를 다시 읽기 때문입니다):
    • 메인라인 — lore.kernel.org, 드라이버 소스, DT 바인딩, 가장 가까운 형제 SoC(동일 제품군 또는 동일 RPM 세대)의 dtsi. "다운스트림 드라이버 포팅" 캠페인 범위를 정하기 전에 메인라인이 이미 인터페이스에 대해 가지고 있는 것을 스위프하십시오: 내보낸 API, 사용자 공간에 도달하는지 커널 내부 전용인지, 게이트(머신 허용 목록, "부트로더에 의해 사전 로드됨" 의미, 내장형 대 모듈)(측정: 이러한 스위프 한 번이 9.4k라인 다운스트림 포트를 ~300라인 프로브 모듈로 줄였습니다. 메인라인이 이미 허용 목록 뒤에 인터페이스를 커널 내부적으로 가지고 있었기 때문입니다. 계획은 기존 API를 구동하는 것이지 포트하는 것이 아니었습니다).
    • 다운스트림 벤더 커널 — GPL 게시 OEM 소스. GPLv2는 Android OEM이 출시한 커널 소스를 게시하도록 의무화하므로, 이 기기에 대한 정확한 릴리즈가 일반적으로 존재합니다: OEM의 오픈 소스 포털(Samsung, Sony, Xiaomi, Fairphone, OnePlus/OPPO 및 Motorola는 모두 운영), GitHub/GitLab 미러, 포털 링크가 끊어진 경우 XDA와 같은 커뮤니티 아카이브. 0단계의 /proc/version과 일치하는 버전 문자열을 가진 tarball을 선택하십시오. 벤더는 여러 빌드를 게시하며 이들은 다릅니다. 컴플라이언스 품질은 다양하므로 트리를 채굴할 오라클로 취급하십시오 — 이 정확한 기기에 대한 보드 dts 및 defconfig, 아웃오브트리 벤더 드라이버(터치, 패널, 충전기, 모뎀 글루) 및 레지스터 시퀀스와 펌웨어 핸드셰이크 — 빌드된다고 가정하지 마십시오. 정확한 릴리즈가 나타나지 않으면, 형제 기기의 릴리즈가 일반적으로 여전히 SoC dtsi를 제공합니다. 더 좋은 것은: 기기 자체에서 가져온 스톡 DTB (dd로 건드리지 않은 부트 슬롯, d00dfeed를 스캔, dtc -I dtb -O dts). 이는 이 보드에 대한 근본 진실이며, 형제 SoC 추측을 두 번 이상 수정했습니다 — 형제 SoC가 잘못 알고 스톡 DTB가 올바르게 알고 있는 SMMU 스트림 ID를 포함합니다.
    • postmarketOS — pmaports 기기 패키지 및 APKBUILD, 병합 요청, 위키 기기 페이지, SoC-메인라인 트리.
    • Halium / UBports — halium/android_device_* 트리, hybris-boot 구성, UBports 기기 포트. Halium은 메인라인이 아닌 Android 벤더 스택을 실행하므로, _벤더 펌웨어_가 어떻게 구동되기를 기대하는지에 대한 최고의 소스입니다: 펌웨어 블롭 경로 및 로드 순서, 데몬이 기대하는 속성 및 소켓 인터페이스, 센서 및 모뎀 HAL 구성. 메인라인 드라이버가 프로브하지만 펌웨어 핸드셰이크가 실패할 때 — 또는 아직 지원되지 않는 주변 장치가 어떤 핸드셰이크를 기대하는지 알아야 할 때 — 이것이 일반적으로 누락된 조각이 기록된 곳입니다.
    • Mobian — 데비안 기기 저장소.
    • NixOS — mobile-nixos 패턴 및 nixpkgs 패키징.

얇은 결과는 정상적인 경우이지 장애물이 아닙니다. 포트에 필요한 대부분은 이 보드에서, 그리고 종종 이 SoC에서 전혀 수행된 적이 없습니다. 여섯 소스가 아무것도 보고하지 않는다는 것은 아무도 작업을 게시하지 않았음을 의미합니다. 작업이 중단되거나 반환되어야 함을 의미하지는 않습니다. 선례가 없을 때, 답은 여전히 주요 아티팩트에 있습니다: 이미 주변 장치를 구동하는 아웃오브트리 벤더 드라이버(레지스터 시퀀스, 펌웨어 핸드셰이크, GPIO 및 레귤레이터 배선), 그것에 대한 스톡 DTB의 자체 노드, 사용자 공간이 기대하는 것을 명명하는 벤더 HAL 구성, 구조적 템플릿으로서 가장 가까운 동일 장치 클래스의 메인라인 드라이버. 그것들을 읽고, 설계를 도출하고, 누락된 조각 — DT 노드, 퀵, 작은 드라이버 — 을 작성하십시오. 그 조각을 저작하는 것은 부트업의 일반적인 최종 상태이며, 정당화되어야 하는 예외가 아닙니다. 0단계 백업과 플래시당 하나의 변수 규칙은 잘못된 도출이 다른 반증과 마찬가지로 한 번의 부팅과 한 줄의 장부를 소모하도록 정확히 존재합니다.

빈 스위프와 빈 스캔은 다른 발견입니다. 소스의 빈 스위프는 아무도 작업을 게시하지 않았음을 의미합니다. 빈 스캔 — 아무것도 반환하지 않는 추출 —은 동일한 방법이 알려진 긍정에 대해 실행되고 적용 범위가 검증될 때까지 무효입니다: 파일 수, 세그먼트 목록, glob이 실제로 일치한 것. 측정된 근접 실패: glob이 27개의 펌웨어 세그먼트 중 9개를 일치시키고 거의 거짓 "펌웨어가 이를 생략한다"를 기록할 뻔했습니다. 라이브러리 스캔은 알려진 칩 ID를 긍정 제어로 찾은 후에야 신뢰할 수 있게 되었습니다.

다운스트림 식별자는 다운스트림의 문제입니다.

(참고: 원본 SKILL.md가 중간에 잘렸지만, 번역은 제공된 내용을 기준으로 완료했습니다. 전체 문서가 제공되면 나머지 부분도 번역할 수 있습니다.)

관련 스킬