Post

[Paper Reproducing] Lenovo y704 rooting

[Paper Reproducing] Lenovo y704 rooting

이전 글에서 다룬 llm.npu에 대한 reproducing에서 NPU utilization 등을 찍어 보려고 했는데, Snapdragon 8 elite를 탑재한 순정 기기에 대해서 snapdragon profiler를 사용했을 때 NPU/DSP 관련 항목이 뜨지 않아 성능을 구체적으로 파악하기 어렵다는 문제가 있었다. 교수님께서 NPU profiling의 경우 rooting을 해서 내부 파일을 직접 확인해봐야 한다고 하셨고, 이에 따라 Lenovo y700 4세대(이하 y704)에 대한 rooting과 profiling을 수행했다. Rooting은 교수님께서 공유해주신 포럼(XDA)에 방법이 나와있어서 이걸 참고해서 진행했다. 결과적으로 rooting 이후 setenforce로 SELinux를 해제해 snapdragon profiler를 사용한 NPU/DSP profiling에 성공했다!

Rooting 과정

포럼의 글과 댓글을 기반으로 rooting을 수행했다. 그 과정은 아래와 같다.

  1. Bootloader unlock
  2. 기기의 init_boot.img 확보
  3. Magisk를 사용해 init_boot.img를 patch한 파일 생성
  4. Magisk로 생성한 파일을 init_boot에 flashing

참고로 이를 진행하기 위해서는 USB 케이블을 사용해 유선 adb 연결을 세팅해놔야 한다.

Bootloader unlock

Rooting을 위해선 먼저 시스템의 가장 기본적인 보안 장치인 bootloader의 잠금을 해제해야 한다. 이는 특정 firmware를 flashing(설치)하거나 자유롭게 수정할 수 있도록 하는 과정이라고 한다.

Bootloader unlock을 위해서는 우선 기기(y704)의 bootloader SN(Serial Number)을 추출해야 한다. 기기의 개발자 설정에서 USB debugging과 OEM unlocking 설정을 ON으로 지정하고, 기기를 컴퓨터에 adb로 연결한 뒤 아래의 명령어로 추출할 수 있다. bootloader SN은 64개의 16진수로 구성되어 있다.

1
adb shell getprop ro.boot.bootload_sn

이후 포럼에서 다운받을 수 있는 sn.img를 hex editior로 열어서 5가 64개인 부분을 찾아 기기의 bootloader SN으로 수정해 저장한다. 그리고 수정한 sn.img 파일을 fastboot로 기기에 flashing한다. fastboot로 flashing하기 위해선 bootloader로 진입해야 하는데, 이는 아래의 adb 명령어로 할 수 있다.

1
adb reboot bootloader

flashing하기 전에 아래의 명령어로 fastboot에서 장치가 인식되는지 확인할 수 있다. y704에는 c타입 포트가 2개 있는데, 태블릿의 짧은 변 쪽이 아니라 긴 변 쪽에 있는 포트에 케이블을 연결해야 fastboot에 인식된다.

1
fastboot devices

인식되었으면 sn.img를 flashing한다.

1
fastboot flash unlock (sn.img path)

flashing이 됐으면 bootloader를 unlock한다. 아래의 명령어를 실행하면 y704에 정말 unlock할 건지에 대한 화면이 뜨는데, 볼륨버튼으로 조작해 unlock할 수 있다.

1
fastboot oem unlock

포럼을 보면 relock했을 때 기기가 벽돌이 된다는 댓글이 있으니 참고하자. 또한 os 버전이 1.1.11.120이면 unlock이 안 된다는 댓글도 있다. 이 경우 downgrade 이후 unlock했다고 하므로 기기의 소프트웨어 업데이트에 주의하자.

init_boot.img 확보

포럼의 글에서는 Qualcomm 9008 tool를 사용하고, 포럼에서 제공하는 y700 (8g4) 9008.melf 파일을 사용해 기기의 init_boot.img를 추출하라고 되어 있다. 9008 driver, QFIL 등을 사용하는 것 같은데, sahara fail이 뜨는 등 찾아봐야 할 부분이 꽤 됐다. 이렇게 하지 않아도, 대신 포럼 댓글에서 제공한 링크에서 os에 대응되는 init_boot.img를 다운받을 수 있다. 중국 사이트긴 한데 포럼에서 별 말 없어서 써도 될 거 같다.

링크에서 다운받은 폴더에 들어가보면 init_boot_a.img와 init_boot_b.img가 있는데, 이는 안정성을 위해 A/B partition 시스템을 사용하기 때문이라고 한다. 즉, 시스템의 핵심 파티션들(init_boot 등)이 A와 B, 두 벌씩 존재해 한쪽은 active이고 다른 한쪽은 inactive이다. rooting을 위해서는 기기가 어떤 슬롯(A or B)을 사용하고 있는지 확인하고, 이후 flashing을 해당 슬롯에 해야 한다. 아래의 명령어로 슬롯을 확인할 수 있다. 내 슬롯은 a여서 이를 고려해 진행했다.

Magisk로 patch하기

init_boot_a.img를 다운받았으면 이후 Magisk를 사용해 추출한 img 파일을 patch하고, y704로 다시 전송한다. Magisk는 안드로이드 루팅 및 루팅 상태 관리를 위한 어플리케이션이다. y704에서 Magisk github의 apk 파일을 다운받아 설치했다.

다운받은 init_boot_a.img을 adb push로 기기에 넘기고(/storage/emulated/0/Download에 넣으면 다운로드 폴더에서 보인다.), 기기에서 설치된 Magisk 어플리케이션을 활용해 해당 파일에 patch할 수 있다. patch하면 Magick_aoxh-29001.img 등의 파일이 생성되는데, 이를 adb pull을 사용해 컴퓨터로 다시 옮긴다.

Rooting 성공!

patch된 파일을 얻었으면 아래의 명령어로 bootloader에 진입한 뒤 fastboot에 기기가 인식되는지 확인하고, patch된 파일을 flashing한 뒤 재부팅한다. 슬롯이 a였으므로 init_boot_a에 flashing한다(궁금하면 partition 이름도 명령어로 찍어볼 수 있다.).

1
2
3
4
adb reboot bootloader
fastboot devices
fastboot flash init_boot_a (Magick_aoxh-29001.img path)
fastboot reboot

이후 기기의 Magisk 앱을 실행하면 SuperUser 항목에서 shell에 root 권한을 부여할 수 있다. 권한 부여 이후 adb shell로 기기에 진입해 su 명령어를 입력해 보면 rooting이 된 것을 확인할 수 있다.

NPU/DSP Profiling

이제 NPU/DSP에 대한 profiling이 가능한지 확인해보자. rooting만 한 경우에는 snapdragon profiler에는 여전히 NPU/DSP 정보가 보이지 않는다. 교수님 말씀대로 직접 내부 파일을 확인해봐야 할 것 같다.

안드로이드 디렉토리 탐색

gemini와 함께 어떤 파일을 뜯어봐야 할지 확인해봤다. NPU/DSP 관련 정보는 /sys의 class, devices, kernel 중에 있을 것이라고 한다. 해당 디렉토리들의 하위 디렉토리들을 하나씩 뜯어보니, /sys/devices/platform/soc/32300000.remoteproc-cdsp와 /sys/kernel/tracing에서 그럴듯한 파일들을 확인할 수 있었다.

/sys/devices/platform/soc/32300000.remoteproc-cdsp는 cDSP에 대한 여러 정보가 있지만 구체적인 profiling 관련 값들이 정리되어 있지는 않다. 반면 /sys/kernel/tracing은 tracing을 하라고 만들어놓은 디렉토리였다. 특정 항목들을 지정해 tracing할 수 있고, 사용법이 나와있는 README도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
TB322FC:/ # ls /sys/devices/platform/soc/32300000.remoteproc-cdsp
driver           subsystem                                                   supplier:platform:320c0000.interconnect  txn_id
driver_override  supplier:platform:16500000.rsc:drv@2:clock-controller       supplier:platform:soc:interconnect@1     uevent
modalias         supplier:platform:16500000.rsc:drv@2:rpmh-regulator-cxlvl   supplier:platform:soc:qcom,smp2p-cdsp    wakeup
of_node          supplier:platform:16500000.rsc:drv@2:rpmh-regulator-mxclvl  supplier:regulator:regulator.11
power            supplier:platform:16500000.rsc:drv@2:rpmh-regulator-nsplvl  supplier:regulator:regulator.18
remoteproc       supplier:platform:1700000.interconnect                      supplier:regulator:regulator.9
TB322FC:/ # 
...
TB322FC:/ # ls /sys/kernel/tracing
README                current_tracer  kprobe_events   saved_cmdlines_size    timestamp_mode    trace_pipe
available_events      dynamic_events  kprobe_profile  saved_tgids            trace             tracing_cpumask
available_tracers     error_log       options         set_event              trace_clock       tracing_on
buffer_percent        events          per_cpu         set_event_notrace_pid  trace_marker      tracing_thresh
buffer_size_kb        free_buffer     printk_formats  set_event_pid          trace_marker_raw  uprobe_events
buffer_total_size_kb  instances       saved_cmdlines  synthetic_events       trace_options     uprobe_profile
TB322FC:/ # 

Profiling 성공!

이런 파일들을 잘 뜯어보고 수정하면 profiling이 가능할 거 같기는 한데, 이는 snapdragon profiler에서는 다양한 값들을 편리하게 볼 수 있는 데에 반해 많이 불편하고 번거로운 작업이다. 실제로 snapdragon profiler에서 DSP 값을 확인하는 기능을 제공하고 있고, 쉘에서 profiling 값을 추출하는 게 가능한 것으로 보아 권한 문제로 snapdragon profiler에서 DSP 관련 항목이 보이지 않는 것으로 판단했다.

gemini를 돌려보니 자신이 제공하는 스크립트를 통해 권한 부여가 가능하다고 한다. 해당 스크립트를 확인 및 실행했더니 DSP 관련 정보가 snapdragon profiler에 보인다! 명령어를 하나씩 뜯어봤더니 아래의 명령어에 의해 DSP 관련 정보가 뜬 것이었다. setenforce 0은 SELinux라는 보안 모듈을 사용하지 않도록 해제하는 명령어다. 즉, SELinux가 DSP 노출을 막고 있었다. setenforce 1로 SELinux가 다시 동작하도록 하면 snapdragon profiler에서 DSP 관련 항목이 다시 뜨지 않는 것을 확인할 수 있었다. 참고로 이 명령어는 root 권한이 있어야 사용이 가능하므로 rooting이 선행되어야 한다.

1
setenforce 0

참고로 기기를 재부팅하면 setenforce 및 권한이 초기화되는 것으로 보인다. 재부팅하면 setenforce 0을 다시 입력해야 하고, snapdragon profiler에서 cDSP 관련 항목이 잘 뜨지 않는 경우에도 재부팅하고 setenforce 0을 해주면 다시 잘 떴다.

아무튼 이제 DSP 관련 profiling 정보를 확인할 수 있다! 실제로 기기의 카메라에서 인물모드를 켜 보면 NPU utilization이 높아지는 것을 확인할 수 있었다. 또한 이전에 reproduce한 llm.npu 코드를 돌려보니 아래 스크린샷과 같이 NPU를 활용하는 prefill phase에서는 30% 언저리의 utilization을 확인할 수 있었고, CPU만 활용하는 decoding phase에서는 거의 0%에 가까운 utilization을 확인할 수 있었다. 생각보다 NPU utilization이 그리 높지 않은 것이 의아하긴 했지만, 그래도 결과는 잘 찍어볼 수 있었다.

This post is licensed under CC BY 4.0 by the author.