0. 前言

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

1. 原理介绍

1.1 fastboot oem bootargs

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

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分区

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

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. 总结

{% tip success %}

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

fastboot oem bootargs "initcall_debug debug log_buf_len=2M"

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

fastboot oem bootargs

{% endtip %}

{% btns rounded center grid2 %}
{% cell 下载源码1, https://hexoimg.oss-cn-shanghai.aliyuncs.com/blog/25/1/23a7114.diff.zip, anzhiyufont anzhiyu-icon-bolt %}
{% cell 下载源码2, https://hexoimg.oss-cn-shanghai.aliyuncs.com/blog/25/1/cdb42d4.diff.zip, anzhiyufont anzhiyu-icon-book %}
{% endbtns %}

4. 代码更新

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. 设置模式
    fastboot oem bootargs set "initcall_debug"
    
  2. 追加模式
    fastboot oem bootargs append "xxxxx"
    
  3. 清除模式
    fastboot oem bootargs set ""