3、源码获取与管理:三星官方BSP发布包结构、Git仓库管理、Repo工具使用、补丁管理基础

好,咱们进入第三章。这一章讲的是源码获取与管理,说白了就是「怎么把三星的BSP拿到手,并且管好它」。我见过不少工程师,拿到BSP就急着编译,结果后面补丁打不上、版本回退不了,搞得焦头烂额。嗯,咱们先把基础打牢。

3.1 三星官方BSP发布包结构

三星官方的BSP发布包,通常是一个压缩包,名字类似 SM-XXXX_BSP_YYYYMMDD.tar.gz。解压之后,你会看到这样的目录结构:

SM-XXXX_BSP/
├── bootloader/          # 引导加载程序(u-boot 或 s-boot)
├── kernel/              # Linux 内核源码
├── platform/            # 硬件平台相关代码
├── tools/               # 烧录工具、脚本
├── docs/                # 文档(英文为主,偶尔有中文)
├── patches/             # 官方补丁集合
└── README.txt           # 必读!说明文件

我个人习惯,拿到包后第一件事不是解压,而是先看 README.txt。为什么?因为里面会写明:

  • 这个BSP对应哪个硬件版本(比如 Rev0.1 还是 Rev1.0)
  • 依赖的交叉编译工具链版本
  • 已知的问题列表
注意: 三星的BSP包经常有多个版本,比如 BSP_v1.0BSP_v1.1。我曾经遇到过,拿 v1.0 的BSP去适配 Rev1.0 的板子,结果死活起不来。后来才发现,Rev1.0 必须用 v1.1 的BSP。所以,版本号一定要对清楚

3.2 Git仓库管理

拿到BSP源码后,我建议你做的第一件事——把它变成一个Git仓库。为什么?因为你要打补丁、要回退、要分支管理。没有Git,后面会乱成一锅粥。

具体做法很简单:

cd SM-XXXX_BSP
git init
git add .
git commit -m "Initial import: Samsung BSP v1.0 for SM-XXXX"

这样,你就有了一个干净的初始提交。以后所有修改,都可以基于这个提交来追踪。

我个人习惯,还会在 .gitignore 里加上:

*.o
*.ko
*.cmd
*.tmp
*.swp
tags/
cscope.*

嗯,这些编译中间文件,没必要进版本管理。

3.3 Repo工具使用

如果你接触过三星的Exynos系列,或者高通的平台,你会发现它们经常用 repo 工具来管理多个Git仓库。Repo本身是一个Python脚本,底层还是调用Git。

三星的BSP,有时候会拆成多个仓库:

  • kernel/ 一个仓库
  • bootloader/ 一个仓库
  • platform/ 一个仓库

这时候,repo initrepo sync 就派上用场了。

举个例子,三星官方通常会提供一个 manifest.xml 文件,里面定义了所有仓库的地址和分支:

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  <remote name="samsung" fetch="https://github.com/Samsung/" />
  <default revision="refs/tags/BSP_v1.0" remote="samsung" />
  <project path="kernel" name="linux-3.18" />
  <project path="bootloader" name="u-boot-samsung" />
  <project path="platform" name="hardware-samsung" />
</manifest>

然后你只需要:

repo init -u https://github.com/Samsung/manifest.git -b BSP_v1.0
repo sync

所有仓库就都拉下来了。是不是很方便?

小技巧: 如果你在公司内网,网络不好,可以先用 repo sync -j4 并行下载。但注意,-j 后面的数字不要太大,否则容易把服务器搞崩。我一般用 -j4-j8

3.4 补丁管理基础

补丁管理,是BSP开发中最常见的操作。你想想看,三星官方发布BSP后,你肯定要针对自己的硬件做修改。这些修改,就是补丁。

补丁的生成,用 git format-patch

git format-patch -1 HEAD   # 生成最近一次提交的补丁
git format-patch -3 HEAD   # 生成最近三次提交的补丁

补丁的应用,用 git am

git am 0001-fix-i2c-clock.patch

如果补丁冲突了,怎么办?嗯,这时候 git am --show-current-patch 可以帮你看看当前冲突的内容。然后手动解决冲突,再 git am --continue

我曾经遇到过一个问题:三星官方给的补丁,是用 diff 命令生成的,不是 git format-patch。这时候 git am 用不了,得用 patch -p1

patch -p1 < 0001-fix-i2c-clock.diff
避坑指南:patch 命令打补丁时,一定要确认 -p 后面的数字。如果补丁文件里的路径是 a/kernel/drivers/i2c.c,而你当前在 kernel/ 目录下,那就要用 -p1 去掉 a/ 前缀。我曾经因为 -p 参数搞错,把补丁打到了错误的目录,排查了半天。

3.5 补丁管理的最佳实践

最后,分享几个我个人的补丁管理习惯:

  1. 每个补丁只做一件事。比如,修复I2C时钟的补丁,就不要混入修改GPIO的内容。这样方便回退和排查。
  2. 补丁命名要有意义。比如 0001-fix-i2c-clock-divider.patch,而不是 0001-my-patch.patch
  3. 维护一个补丁队列。我习惯在 patches/ 目录下,按功能分类存放补丁:
patches/
├── 0001-fix-i2c-clock.patch
├── 0002-add-gpio-key.patch
└── 0003-enable-usb-host.patch

这样,每次编译前,我可以清楚地知道打了哪些补丁。

核心要点: 补丁管理,本质上就是「记录你的修改」。不要偷懒,不要把所有修改都堆在一个补丁里。否则,出了问题你都不知道是哪个修改导致的。

好了,这一章就到这里。下一章,我们会讲如何搭建交叉编译环境,以及如何配置工具链。嗯,那才是真正开始动手的地方。