[Android稳定性] 第008篇 [原理篇] 动态设置kernel cmdline

0. 前言

有时候我们会遇到一些问题,需要去打开内核的一些参数进行一些调试,比如initcall_debugdebuglog_buf_len等等。每次遇到这些问题时,我们都需要去重新打包。这不仅仅浪费时间,而且有时候在遇到问题时重新编译后反而不复现了,妥妥的浪费时间。基于这样的需求,我实现了这样的需求。

1. 原理介绍

1.1 fastboot oem bootargs

首先扩展fastboot oem指令,接收fastboot模式下输入的内核参数,并写入到devinfo分区中保存起来(重启不会被恢复)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
diff --git a/QcomModulePkg/Library/FastbootLib/FastbootCmds.c b/QcomModulePkg/Library/FastbootLib/FastbootCmds.c
index 0169b2b..aedb79e 100644
--- a/QcomModulePkg/Library/FastbootLib/FastbootCmds.c
+++ b/QcomModulePkg/Library/FastbootLib/FastbootCmds.c
@@ -3677,6 +3677,34 @@
FastbootOkay ("");
}

+STATIC VOID
+CmdOemSetBootargs (CONST CHAR8 *arg, VOID *data, UINT32 sz)
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ CHAR8 BootArgs[256] = "";
+
+ AsciiStrnCatS (BootArgs,
+ 256,
+ arg,
+ AsciiStrLen(arg));
+
+ if (AsciiStrLen (BootArgs) > 256) {
+ FastbootFail("SetBootargs command only support 256 byte!");
+ return ;
+ }
+
+ DEBUG((EFI_D_ERROR, "CmdOemSetBootargs BootArgs=%a\n", BootArgs));
+
+ Status = SetBootargs(BootArgs);
+ if (Status != EFI_SUCCESS){
+ FastbootFail("Set bootargs fail");
+ }else{
+ FastbootInfo("Set bootargs successful\n");
+ WaitForTransferComplete();
+ FastbootOkay("");
+ }
+}
+
#define VBMETA_ROLLBACK_LOC (2)
STATIC VOID CmdOemEraseVbIndex()
{
@@ -4239,6 +4267,7 @@
{"getvar:", CmdGetVar},
{"download:", CmdDownload},
{"oem audio-framework", CmdOemAudioFrameWork},
+ {"oem bootargs", CmdOemSetBootargs},
};

/* Register the commands only for non-user builds */

1.2 写bootargs到devinfo分区

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
diff --git a/QcomModulePkg/Library/BootLib/DeviceInfo.c b/QcomModulePkg/Library/BootLib/DeviceInfo.c
index e2ecf09..bbf4621 100644
--- a/QcomModulePkg/Library/BootLib/DeviceInfo.c
+++ b/QcomModulePkg/Library/BootLib/DeviceInfo.c
@@ -136,6 +136,26 @@
return Status;
}

+VOID
+GetBootargs(CHAR8 *BootArgs, UINT32 Len)
+{
+ AsciiSPrint(BootArgs, Len, "%a", DevInfo.bootargs);
+}
+
+EFI_STATUS
+SetBootargs (CHAR8 *BootArgs)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ AsciiStrnCpyS(DevInfo.bootargs, MAX_BOOTARGS_LEN, BootArgs, AsciiStrLen(BootArgs));
+
+ DEBUG((EFI_D_ERROR, "[LIUQI] SetBootargs DevInfo.bootargs = %a\n", DevInfo.bootargs));
+
+ Status = ReadWriteDeviceInfo (WRITE_CONFIG, &DevInfo, sizeof (DevInfo));
+
+ return Status;
+}
+
EFI_STATUS
StoreAudioFrameWork (CONST CHAR8 *CmdLine, UINT32 CmdLineLen)
{

1.3 更新kernel cmdline

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
diff --git a/QcomModulePkg/Library/BootLib/UpdateCmdLine.c b/QcomModulePkg/Library/BootLib/UpdateCmdLine.c
index 714fd14..306b49a 100644
--- a/QcomModulePkg/Library/BootLib/UpdateCmdLine.c
+++ b/QcomModulePkg/Library/BootLib/UpdateCmdLine.c
@@ -305,6 +305,8 @@
STATIC CONST CHAR8 *MemHpState = " memhp_default_state=online";
STATIC CONST CHAR8 *MovableNode = " movable_node";

+STATIC CHAR8 BootargsCmdLine[MAX_BOOTARGS_LEN] = "";
+
STATIC CONST CHAR8 *WarmResetArgs = " reboot=w";

STATIC CONST CHAR8 *rfConnect_ture = " androidboot.rf_connect_status=1";
@@ -1330,6 +1332,11 @@
AsciiStrCatS (Dst, MaxCmdLineLen, Src);
}

+ if (Param->BootargsCmdLine) {
+ Src = Param->BootargsCmdLine;
+ AsciiStrCatS (Dst, MaxCmdLineLen, Src);
+ }
+
return EFI_SUCCESS;
}
CHAR8* RemoveSpace (CHAR8* param, UINT32 ParamLen)
@@ -1796,6 +1803,10 @@
ADD_PARAM_LEN (BootConfigFlag, AsciiStrLen (RPMB_BUF),
CmdLineLen, BootConfigLen);

+ GetBootargs(BootargsCmdLine, sizeof(BootargsCmdLine));
+ DEBUG ((EFI_D_ERROR, "[ILIUQI] Get bootargs from devinfo: %a ;\n", BootargsCmdLine));
+ CmdLineLen += AsciiStrLen(BootargsCmdLine);
+
/* Ignore the EFI_STATUS return value as the default Battery Status = 0 and is
* not fatal */
TargetPauseForBatteryCharge (&BatteryStatus);
@@ -2285,6 +2296,7 @@
Param.SystemdSlotEnv = SystemdSlotEnv;
Param.secureboot_status = secureboot_status;
Param.ModemPathCmdLine = ModemPathStr;
+ Param.BootargsCmdLine = BootargsCmdLine;

if(TRUE == SmemBoardId) {
Param.HwVersion = HwVersion;

2. 实验测试

2.1 fastboot oem bootargs initcall_debug

2.2 fastboot oem bootargs debug

3. 总结

支持多种配置生效,最大支持256byte的长度

fastboot oem bootargs “initcall_debug debug log_buf_len=2M”

因为是永久生效,所以如果想去掉,需要再次执行清除指令清除

fastboot oem bootargs