2025年8月6日 星期三

Linux kernel minor upgrade

 今天嘗試把 kernel v4.19.98 作微升級,要升級到 v4.19.325,因為我們原本的 kernel 並不是原生最乾淨的 Linux kernel v4.19.98(是拿MTK平台的 SDK),先講我打上了這兩個版本中間的 patch,但最終編譯,卻有一堆error,解不完

 但我認為,作這件事情,中間的過程,是值得作個記錄的,因此寫了這篇文章,來記錄中間所做的步驟。

1. 下載 Linux 的 branch,使用指令如下:
git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git

2. 每個版本都有打上tag,因此我們可以先 checkout 到 v4.19.325
git checkout v4.19.325

3. git log 確認一下 v4.19.325 與 v4.19.98 分別的 commit hash 號碼是多少










4. 使用指令,把 98 ~ 325 這中間的 commit 都作成 patch 檔,指令如下:
git format-patch d183c8e2647a7d45202c14a33631f6c09020f8ac..a67e7cdde7cc7984ae24c3c81a70dc1aa34424b1 -o patch/

5. 可以看到,目前目錄底下,會產出資料夾 patch/ ,裡面有 19xxx個patch 檔,依序都做好了編號

6. 接著我們準備要來打 patch,先說明一下,我目前的目錄環境是這樣,
apps/src/kernel/linux/4.19/,我目前專案的 repository 是在 apps底下,也就是我可以在 apps底下執行 git log,可以看到以往的 commit 資訊,而目前是要把 linux patch 打到   apps/src/kernel/linux/4.19/ 底下

7. 因為第6.的關係,我們把 patch/ 移動到 apps底下,我們打patch 的指令會如下:
cd apps/
git am --directory=src/kernel/linux/v4.19 patch/* -3  

(加上 -3(或 --3way)後,如果直接套用失敗,Git 會嘗試用三方合併的方式來解決衝突,這樣有時候可以自動解決一些簡單的衝突)

8. 打patch 的途中,會遇到許多的 conflict,你會需要開啟檔案,去解衝突,但我發現 19xxx筆patch,要解的 conflict 實在太多了,後來遇到 conflict 直接使用以下command,意思是直接幫我把衝突的舊檔案的部分刪除,把新的patch 新增的內容,改到檔案裡面: 
git checkout --theirs $file (file帶入中途的檔案路徑 與 名稱)

9. 途中會遇到一些,甚麼都沒改的 patch,會需要手動執行 git am --skip 來繼續,另外解完 conflict 的檔案,要手動執行 git am --continue 來讓 git am 繼續跑

10. 另外有遇到一個,git am 打patch,我發現有一個限制,就是打到 9999個 patch的時候,你再輸入 git am --continue 會沒辦法繼續,如下圖,這時候你必須要先 git push,把先前打的patch 都git push,然後再繼續從第 10000筆繼續打,我的作法是




   







   a. 在作第4部的時候,也順便把檔案列表資訊,輸出到一個檔案:
git format-patch d183c8e2647a7d45202c14a33631f6c09020f8ac..a67e7cdde7cc7984ae24c3c81a70dc1aa34424b1 -o patch/ > patch_list.txt
   b. 想辦法使用 note 或是 Notepad++ 把這些列表改成
rm 0001-xxxx
rm 0002-xxxx
..
rm 9999-xxxx
   c. 切換到 patch/ 資料夾,把 0001~9999 的patch 檔案都刪除
   d. 在接著使用git am 的命令繼續打剩餘的 patch:
git am --directory=src/kernel/linux/v4.19 patch/* -3  


結論: 
   1. 我在這次的過程中,寫了以下兩隻script,當發生conflict,就使用git checkout --theirs $file 去解conflict,因此可以一直遞迴去處理patch,但遇到 git am --continue 無法繼續的空內容,目前就是手動去下 git am --skip
   2. 其實比較好的做法,應該要是以下步驟
        a. 先 git checkout 到 linux pure v4.19.98
        b. 把vendor最一開始給的 kernel 覆蓋到
 linux pure v4.19.98
        c. git diff 看一下改了那些檔案
        d. 直接把 
linux pure v4.19.98,checkout 到 v4.19.325,然後試著把 前一步驟,git diff 的改回去,但如果真的差異太大,就是一個很大的工程了....

以下分享我的兩個 shell script: (主要就是執行 ./for_loop.sh)

主程式:  for_loop.sh

#!/bin/sh
for i in {1..20000}
do
    ./fail_process.sh
    if [ $? -eq 2 ]; then
        echo "fail_process.sh failed, stopping loop."
        break
    fi
done

副程式:  fail_process.sh

#!/bin/sh

# Get the list of files marked as "both modified" from gg (git status)
files0=$(git status | grep "both modified:" | awk -F: '{print $2}' | xargs)

# For each file, run git add
for file in $files0; do
    echo "Processing $file ..."
    git checkout --theirs $file
    git add $file
done


# Get the list of files marked as "deleted by them:" from gg (git status)
files1=$(git status | grep "deleted by them:" | awk -F: '{print $2}' | xargs)

# For each file, run git add
for file in $files1; do
    echo "Processing $file ..."
    git add $file
done

# Get the list of files marked as "deleted by us:" from gg (git status)
files2=$(git status | grep "deleted by us:" | awk -F: '{print $2}' | xargs)

# For each file, run git add
for file in $files2; do
    echo "Processing $file ..."
    git add $file
done


# Get the list of files marked as "both added" from gg (git status)
files3=$(git status | grep "both added:" | awk -F: '{print $2}' | xargs)

# For each file, run git add
for file in $files3; do
    echo "Processing $file ..."
    git checkout --theirs $file
    git add $file
done

if [ -z "$files0" ] && [ -z "$files1" ] && [ -z "$files2" ] && [ -z "$files3" ]; then
        exit 2
fi

git status
git am --continue



沒有留言:

張貼留言