[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

4. 代码更新

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
From cdb42d42448706ce32c641dfdb079e3235221b69 Mon Sep 17 00:00:00 2001
From: liuqi <p-liuqi1@xiaomi.com>
Date: Tue, 24 Dec 2024 18:30:43 +0800
Subject: [PATCH] [O19][Stability] bugfix for long oem bootargs size

HTH-488160

Signed-off-by: liuqi <p-liuqi1@xiaomi.com>
Change-Id: I27489f5be44eec9200ec8cd2e116c4f142a47bd8
---

diff --git a/QcomModulePkg/Include/Library/DeviceInfo.h b/QcomModulePkg/Include/Library/DeviceInfo.h
index 3cba1f6..e35de7b 100644
--- a/QcomModulePkg/Include/Library/DeviceInfo.h
+++ b/QcomModulePkg/Include/Library/DeviceInfo.h
@@ -165,5 +165,5 @@
SetFDRFlag (VOID);

VOID GetBootargs (CHAR8 *BootArgs, UINT32 Len);
-EFI_STATUS SetBootargs (CHAR8 *BootArgs);
+EFI_STATUS SetBootargs (CHAR8 *BootArgs, BOOLEAN mode);
#endif
diff --git a/QcomModulePkg/Library/BootLib/DeviceInfo.c b/QcomModulePkg/Library/BootLib/DeviceInfo.c
index bbf4621..c22f489 100644
--- a/QcomModulePkg/Library/BootLib/DeviceInfo.c
+++ b/QcomModulePkg/Library/BootLib/DeviceInfo.c
@@ -142,15 +142,24 @@
AsciiSPrint(BootArgs, Len, "%a", DevInfo.bootargs);
}

+/* mode:
+ * 1: set mode
+ * 0: append mode
+ */
EFI_STATUS
-SetBootargs (CHAR8 *BootArgs)
+SetBootargs (CHAR8 *BootArgs, BOOLEAN mode)
{
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));
-
+ if (mode == TRUE) {
+ // set mode
+ AsciiStrnCpyS(DevInfo.bootargs, MAX_BOOTARGS_LEN, BootArgs, AsciiStrLen(BootArgs));
+ DEBUG((EFI_D_ERROR, "[LIUQI] bootargs set DevInfo.bootargs = %a\n", DevInfo.bootargs));
+ } else {
+ // append mode
+ AsciiStrnCatS(DevInfo.bootargs, MAX_BOOTARGS_LEN, BootArgs, AsciiStrLen(BootArgs));
+ DEBUG((EFI_D_ERROR, "[LIUQI] bootargs append DevInfo.bootargs = %a\n", DevInfo.bootargs));
+ }
Status = ReadWriteDeviceInfo (WRITE_CONFIG, &DevInfo, sizeof (DevInfo));

return Status;
diff --git a/QcomModulePkg/Library/FastbootLib/FastbootCmds.c b/QcomModulePkg/Library/FastbootLib/FastbootCmds.c
index 928e044..ec08002 100644
--- a/QcomModulePkg/Library/FastbootLib/FastbootCmds.c
+++ b/QcomModulePkg/Library/FastbootLib/FastbootCmds.c
@@ -3738,31 +3738,79 @@
}

STATIC VOID
-CmdOemSetBootargs (CONST CHAR8 *arg, VOID *data, UINT32 sz)
+CmdOemBootargs (CONST CHAR8 *arg, VOID *data, UINT32 sz)
{
EFI_STATUS Status = EFI_INVALID_PARAMETER;
- CHAR8 BootArgs[256] = "";
+ CHAR8 BootArgs[MAX_BOOTARGS_LEN] = "";
+ CHAR8 BootArgsOld[MAX_BOOTARGS_LEN] = "";
+ CHAR8 Resp[MAX_BOOTARGS_LEN] = "";
+ CHAR8 *prefix_get = " get";
+ CHAR8 *prefix_append = " append";
+ CHAR8 *prefix_set = " set";
+ UINT32 prefix_len = 0;

AsciiStrnCatS (BootArgs,
- 256,
+ MAX_BOOTARGS_LEN,
arg,
AsciiStrLen(arg));

- if (AsciiStrLen (BootArgs) > 256) {
- FastbootFail("SetBootargs command only support 256 byte!");
+ if (AsciiStrLen (BootArgs) >= 63) {
+ FastbootFail("fastboot command only support 64 byte!\nPlease try another command for try!\n"
+ "fastboot oem setbootargs +xxx\nIt will append the strings to bootargs\n");
return ;
}

- DEBUG((EFI_D_ERROR, "CmdOemSetBootargs BootArgs=%a\n", BootArgs));
+ DEBUG((EFI_D_ERROR, "CmdOemBootargs command=%a\n", BootArgs));

- Status = SetBootargs(BootArgs);
- if (Status != EFI_SUCCESS){
- FastbootFail("Set bootargs fail");
- }else{
- FastbootInfo("Set bootargs successful\n");
- WaitForTransferComplete();
+ // append or set mode
+ if (!AsciiStrnCmp(BootArgs, prefix_append, AsciiStrLen(prefix_append))) {
+ // append mode
+ GetBootargs(BootArgsOld, sizeof(BootArgsOld));
+
+ if (AsciiStrLen(BootArgs) > (MAX_BOOTARGS_LEN - AsciiStrLen(BootArgsOld))) {
+ FastbootFail("devinfo only support 256 byte bootargs And It will overflow the maximum limit.\n");
+ return ;
+ }
+
+ prefix_len = AsciiStrLen(prefix_append);
+
+ CopyMem(BootArgs, BootArgs+prefix_len, AsciiStrLen(BootArgs) - prefix_len +1);
+
+ Status = SetBootargs(BootArgs, FALSE);
+ if (Status != EFI_SUCCESS){
+ FastbootFail("Set bootargs fail");
+ }else{
+ FastbootInfo("Set bootargs successful\n");
+ WaitForTransferComplete();
+ FastbootOkay("");
+ }
+
+ } else if (!(AsciiStrnCmp(BootArgs, prefix_set, AsciiStrLen(prefix_set)))) {
+ // set mode
+ prefix_len = AsciiStrLen(prefix_set);
+
+ CopyMem(BootArgs, BootArgs+prefix_len, AsciiStrLen(BootArgs) - prefix_len +1);
+ Status = SetBootargs(BootArgs, TRUE);
+ if (Status != EFI_SUCCESS){
+ FastbootFail("Set bootargs fail");
+ }else{
+ FastbootInfo("Set bootargs successful\n");
+ WaitForTransferComplete();
+ FastbootOkay("");
+ }
+
+ } else if (!(AsciiStrnCmp(BootArgs, prefix_get, AsciiStrLen(prefix_get)))) {
+ GetBootargs(Resp, sizeof(Resp));
+
+ FastbootInfo(Resp);
+ WaitForTransferComplete ();
+ FastbootInfo("Get bootargs successful\n");
+ WaitForTransferComplete ();
FastbootOkay("");
+ } else {
+ FastbootFail("Unknown command!\n");
}
+
}

#define VBMETA_ROLLBACK_LOC (2)
@@ -4336,7 +4384,7 @@
{"getvar:", CmdGetVar},
{"download:", CmdDownload},
{"oem audio-framework", CmdOemAudioFrameWork},
- {"oem bootargs", CmdOemSetBootargs},
+ {"oem bootargs", CmdOemBootargs},
};

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


代码更新后,指令执行如下

  1. 设置模式
    1
    fastboot oem bootargs set "initcall_debug"
  2. 追加模式
    1
    fastboot oem bootargs append "xxxxx"
  3. 清除模式
    1
    fastboot oem bootargs set ""