OpenHarmony移植案例與原理:startup子系統之syspara_lite系統屬性部件

語言: CN / TW / HK
摘要:本文介紹下移植開發板時如何適配系統屬性部件syspara_lite,並介紹下相關的執行機制原理。

本文分享自華為雲社群《openharmony移植案例與原理 - startup子系統之syspara_lite系統屬性部件》,作者: zhushy 。

系統屬性部件syspara_lite負責提供獲取與設定作業系統相關的系統屬性,包括預設系統屬性、OEM廠商系統屬性和自定義系統屬性。為滿足OpenHarmony產品相容性規範,產品解決方案需要實現獲取裝置資訊的介面,如:產品名、品牌名、廠家名等,同時提供設定/讀取系統屬性的介面。系統屬性部件syspara_lite包含系統引數特性syspara_lite和token。系統屬性部件syspara_lite定義在build\lite\components\startup.json。原始碼目錄如下:

base/startup/syspara_lite/    # 系統屬性部件
├── frameworks                # 系統屬性部件原始檔目錄
├── hals                      # 系統屬性部件硬體抽象層標頭檔案目錄
└── interfaces                # 系統屬性部件對外介面目錄

系統引數syspara適配

適配啟動恢復子系統startup的syspara_lite部件的一個例項vendor\bestechnic\display_demo\config.json的程式碼片段如下,⑴處的配置項enable_ohos_startup_syspara_lite_use_posix_file_api設定為true,下文通過分析syspara_lite部件的程式碼來解釋。

  {
  "product_name": "display_demo",
    ......
  "subsystems": [
    {
    ......
    {
      "subsystem": "startup",
      "components": [
        {
          "component": "bootstrap_lite"
        },
        {
          "component": "syspara_lite",
          "features": [
⑴           "enable_ohos_startup_syspara_lite_use_posix_file_api = true"
          ]
        }
      ]
    },
    ......
  ],
  "vendor_adapter_dir": "",
  "product_adapter_dir": "//vendor/bestechnic/display_demo/hals",
    ......
}

我們知道,syspara_lite部件支援獲取和設定作業系統的引數,當設定系統引數時,系統引數會最終寫到檔案中進行持久化儲存。在輕量系統中,檔案操作相關介面有POSIX介面與HalFiles介面這兩套實現。POSIX檔案系統介面程式碼位置kernel\liteos_m\kal\libc\musl\fs.c,HalFiles檔案系統介面位置為utils\native\lite\file\src\file_impl_hal\file.c。當對接核心的檔案系統,採用POSIX相關的介面時,需要在features欄位中需要增加enable_ohos_startup_syspara_lite_use_posix_file_api = true。如果對接HalFiles相關的介面,則無須修改。enable_ohos_startup_syspara_lite_use_posix_file_api預設為false,定義在檔案base\startup\syspara_lite\frameworks\parameter\config.gni。我們通過看下編譯配置檔案來了解下實現的原理機制,開啟檔案base\startup\syspara_lite\frameworks\parameter\src\BUILD.gn,片段如下。

⑴處解釋了上文的配置引數enable_ohos_startup_syspara_lite_use_posix_file_api。⑵處依賴產品解決方案中的適配的sys_param實現程式碼。ohos_product_adapter_dir是產品解決方案config.json中的配置項,該配置項一遍設定為"hals"。sys_param實現程式碼檔案的路徑一遍為"hals/utils/sys_paramn/hal_sys_param.c",並且同級目錄的BUILD.gn檔案中的靜態庫名稱必須為hal_sysparam。⑶處表示如果需要使用安全函式,則需要配置項enable_ohos_startup_syspara_lite_use_thirdparty_mbedtls設定為true。⑷處設定一些配置項巨集,這些屬於構建類別的引數。

if (ohos_kernel_type == "liteos_m") {
  static_library("sysparam") {
    include_dirs = [
      "//base/startup/syspara_lite/interfaces/kits",
      "//utils/native/lite/include",
      "//base/startup/syspara_lite/frameworks/parameter/src",
      "//base/startup/syspara_lite/hals",
      "//third_party/mbedtls/include",
    ]
    sources = [ "parameter_common.c" ]
⑴  if (enable_ohos_startup_syspara_lite_use_posix_file_api) {
      sources += [ "param_impl_posix/param_impl_posix.c" ]
    } else {
      sources += [ "param_impl_hal/param_impl_hal.c" ]
    }

⑵  deps = [ "$ohos_product_adapter_dir/utils/sys_param:hal_sysparam" ]
⑶  if (enable_ohos_startup_syspara_lite_use_thirdparty_mbedtls) {
      deps += [ "//third_party/mbedtls:mbedtls" ]
    }

    if (enable_ohos_startup_syspara_lite_use_posix_file_api) {
      deps += [ "//third_party/bounds_checking_function:libsec_static" ]
    }
    defines = [
⑷    "INCREMENTAL_VERSION=\"${ohos_version}\"",
      "BUILD_TYPE=\"${ohos_build_type}\"",
      "BUILD_USER=\"${ohos_build_user}\"",
      "BUILD_TIME=\"${ohos_build_time}\"",
      "BUILD_HOST=\"${ohos_build_host}\"",
      "BUILD_ROOTHASH=\"${ohos_build_roothash}\"",
      "USE_MBEDTLS",
      "DATA_PATH=\"${config_ohos_startup_syspara_lite_data_path}\"",
    ]
  }
}

看個產品解決方案的實際例子,vendor\bestechnic\display_demo\hals\utils\sys_param\BUILD.gn的程式碼如下,⑴處的靜態庫的名字是不能隨意更改的,見上文解釋。

⑴  static_library("hal_sysparam") {
    sources = [ "hal_sys_param.c" ]
    include_dirs = [ "//base/startup/syspara_lite/hals" ]
    defines = [
        "INCREMENTAL_VERSION=\"${ohos_version}\"",
        "BUILD_TYPE=\"${ohos_build_type}\"",
        "BUILD_USER=\"${ohos_build_user}\"",
        "BUILD_TIME=\"${ohos_build_time}\"",
        "BUILD_HOST=\"${ohos_build_host}\"",
        "BUILD_ROOTHASH=\"${ohos_build_roothash}\"",
    ]
    }

檔案vendor\bestechnic\display_demo\hals\utils\sys_param\hal_sys_param.c實現介面檔案base\startup\syspara_lite\hals\hal_sys_param.h中宣告的函式,如下所示,主要包含裝置廠商資訊,軟體版本資訊,構建資訊等。

const char* HalGetDeviceType(void);
const char* HalGetManufacture(void);
const char* HalGetBrand(void);
const char* HalGetMarketName(void);
const char* HalGetProductSeries(void);
const char* HalGetProductModel(void);
const char* HalGetSoftwareModel(void);
const char* HalGetHardwareModel(void);
const char* HalGetHardwareProfile(void);
const char* HalGetSerial(void);
const char* HalGetBootloaderVersion(void);
const char* HalGetAbiList(void);
const char* HalGetDisplayVersion(void);
const char* HalGetIncrementalVersion(void);
const char* HalGetBuildType(void);
const char* HalGetBuildUser(void);
const char* HalGetBuildHost(void);
const char* HalGetBuildTime(void);
int HalGetFirstApiVersion(void);

在適配HalGetSerial介面時,開發板不像產線生產過程那樣,會寫入一個具體的序列號Serial Number,因而需要確定一個數據對開發板進行唯一標識。vendor\bestechnic\display_demo\hals\utils\sys_param\hal_sys_param.c中提供了一種方法,採用WiFi Mac地址進行適配。

const char* HalGetSerial(void)
{
    char macAddr[ETH_ALEN];
    // as devboard has no production serial number, we just
    // use wifi mac address as device serial number.
    if (serialNumber[0] == STR_END_FLAG) {
        extern int bwifi_get_own_mac(u8 *addr);
        bwifi_get_own_mac(macAddr);
        int j = 0;
        for (int i = 0; i < ETH_ALEN; i++) {
            u8 lowFour, highFour;
            highFour = (macAddr[i] & MAC_HIGH_MASK) >> MAC_BITS;
            serialNumber[j] = Hex2Char(highFour);
            j++;
            lowFour = macAddr[i] & MAC_LOW_MASK;
            serialNumber[j] = Hex2Char(lowFour);
            j++;
        }
    }
    return serialNumber;
}

Token令牌適配

在檔案base\startup\syspara_lite\hals\hal_token.h中定義令牌相關的介面宣告,包含寫令牌,獲取AcKey,獲取產品編碼和產品鍵值。在移植開發板時,需要實現這些介面。

在base\startup\syspara_lite\frameworks\token\BUILD.gn檔案中,檢視令牌如何編譯的,以LiteOS-M為例,片段為:
⑴處可以看出編譯使用的原始檔是"src/token_impl_hal/token.c",對於linux和liteos-a核心使用的原始檔是"src/token_impl_posix/token.c"。"token.c"檔案程式碼很簡單,判斷下引數然後呼叫產品解決方案中的適配函式,比如函式ReadToken()會呼叫HalReadToken()函式。

⑵處需要注意,這裡依賴的就是產品解決方案適配的token實現程式碼。ohos_product_adapter_dir是產品解決方案config.json中的配置項,該配置項一遍設定為"hals"。token實現程式碼檔案的路徑一遍為"hals/utils/token/hal_token.c",並且同級目錄的BUILD.gn檔案中的靜態庫名稱必須為hal_token_static。⑶處表示token部件由特性token_static組成。

    if (ohos_kernel_type == "liteos_m") {
    static_library("token_static") {
⑴      sources = [ "src/token_impl_hal/token.c" ]

        include_dirs = [
        "//base/startup/syspara_lite/interfaces/kits",
        "//utils/native/lite/include",
        "//base/hiviewdfx/hilog_lite/interfaces/native/kits/hilog_lite",
        "//base/startup/syspara_lite/hals",
        ]

⑵      deps = [ "$ohos_product_adapter_dir/utils/token:hal_token_static" ]
    }
    }

    lite_component("token") {
    features = []
    if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux") {
        features += [ ":token_shared" ]
    }
    if (ohos_kernel_type == "liteos_m") {
⑶      features += [ ":token_static" ]
    }
    }

看個產品解決方案的實際例子,vendor\bestechnic\display_demo\hals\utils\token\BUILD.gn的程式碼如下,⑴處的靜態庫的名字是不能隨意更改的,見上文解釋。

⑴  static_library("hal_token_static") {
    sources = [ "hal_token.c" ]

    include_dirs = [
        "//base/startup/syspara_lite/hals",
        "//utils/native/lite/include",
    ]
    deps = []
    }

檔案vendor\bestechnic\display_demo\hals\utils\token\hal_token.c中的令牌實現程式碼片段如下,當前均為空實現,沒有實際使用起來。

static int OEMReadToken(char *token, unsigned int len)
{
    // OEM need add here, read token from device
    (void)(token);
    (void)(len);
    return EC_SUCCESS;
}
......
int HalReadToken(char *token, unsigned int len)
{
    if (token == NULL) {
        return EC_FAILURE;
    }

    return OEMReadToken(token, len);
}

系統引數syspara_lite部件使用例子

下面是系統引數syspara_lite部件使用例子,來自https://gitee.com/openharmony/startup_syspara_lite⑴處獲取裝置型別,⑵處獲取廠商名稱,⑶處獲取品牌名稱。其他系統屬性介面呼叫的例子類似,詳細的介面說明下文會提供。

⑴  char* value1 = GetDeviceType();
    printf("Device type =%s\n", value1);
    free(value1);
⑵  char* value2 = GetManufacture();
    printf("Manufacture =%s\n", value2);
    free(value2);
⑶  char* value3 = GetBrand();
    printf("GetBrand =%s\n", value3);
    free(value3);

系統引數syspara_lite部件介面資訊

在檔案base\startup\syspara_lite\interfaces\innerkits\native\syspara\include\parameter.h中定義了系統屬性的介面。系統屬性介面說明如下表所示:

參考站點

 

點選關注,第一時間瞭解華為雲新鮮技術~