Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Subsystem Integration and Boot Sequence Adaptation for OpenHarmony

Tech May 16 2

OpenHarmony organizes its functionality through a modular hierarchy consisting of systems, subsystems, and components. This architecture enables engineers to selectively disable non-essential modules based on hardware constraints and product specifications. To successfully deploy the framework on a new silicon platform, developers must properly adapt the required subsystems.

Subsystem Core Responsibility
applications Repository for demonstration applications and vendor-specific source modules.
kernel Core OS layer handling process scheduling, IPC, and dynamic memory allocation.
hiviewdfx Observability framework providing log aggregation, fault injection, and diagnostic utilities.
communication Wireless connectivity stacks for Wi-Fi, Bluetooth, and cellular protocols.
iothardware Hardware abstraction layer exposing standard IoT interfaces (GPIO, SPI, I2C, UART).
startup Orchestrates the boot pipeline from kernel handoff to application framework readiness.
update Manages firmware delivery and Over-The-Air (OTA) patching mechanisms.
utils Foundational C/C++ runtime libraries and cross-platform helper APIs.
distributed_schedule Enables cross-device service discovery, component binding, and distributed execution.
security Implements application sandboxing, cryptographic key management, access control, and data integrity verification.
test Provides automated validation frameworks, unit testing utilities, and continuous integration hooks.

The startup subsystem governs the initialization sequence that occurs immediately after the kernel hands over execution to the framework. On lightweight devices, the System Ability Manager (SAMGR) identifies bootstrap entry points via predefined markers. Once hardware prerequisites are satisfied, ivnoking the core initialization routine triggers the sequential activation of system services.

The primary boot sequence executes initialization routines stored in designated ELF segments, enforcing a strict phase order before transferring control to the service registry.

void OsInitializeCoreFramework(void)
{
    MODULE_INIT(bsp);           // Iterates .zinitcall.bspX.init section
    MODULE_INIT(device);        // Iterates .zinitcall.deviceX.init section
    MODULE_INIT(core);          // Iterates .zinitcall.coreX.init section
    SYS_INIT(service);          // Iterates .zinitcall.sys.serviceX.init section
    SYS_INIT(feature);          // Iterates .zinitcall.sys.featureX.init section
    MODULE_INIT(run);           // Iterates .zinitcall.runX.init section
    SAMGR_Bootstrap();          // Finalizes service manager and registers system abilities
}

Configuration Integration

To bind the boot framework, the product definition must explicitly declare the startup components. Modify config.json within the vendor directory to include the following module references:

{
  "subsystem_name": "startup",
  "components": [
    { "component_name": "bootstrap_lite", "features": [] },
    { "component_name": "syspara_lite", "features": [] }
  ],
  "product_adapter_dir": "vendor/MyVendorCompany/MyProduct/hals"
}

Components such as syspara_lite depend on adapter utilities located in the path defined by product_adapter_dir.

Linker Script Modification

The toolchain must preserve initializasion function pointers across distinct memory segments. Inject the following directives into the vendor-specific linker script to correctly map the .text region:

    __zinitcall_bsp_start = .;
    KEEP(*(.zinitcall.bsp0.init))
    KEEP(*(.zinitcall.bsp1.init))
    KEEP(*(.zinitcall.bsp2.init))
    KEEP(*(.zinitcall.bsp3.init))
    KEEP(*(.zinitcall.bsp4.init))
    __zinitcall_bsp_end = .;
    
    __zinitcall_device_start = .;
    KEEP(*(.zinitcall.device0.init))
    KEEP(*(.zinitcall.device1.init))
    KEEP(*(.zinitcall.device2.init))
    KEEP(*(.zinitcall.device3.init))
    KEEP(*(.zinitcall.device4.init))
    __zinitcall_device_end = .;
    
    __zinitcall_core_start = .;
    KEEP(*(.zinitcall.core0.init))
    KEEP(*(.zinitcall.core1.init))
    KEEP(*(.zinitcall.core2.init))
    KEEP(*(.zinitcall.core3.init))
    KEEP(*(.zinitcall.core4.init))
    __zinitcall_core_end = .;
    
    __zinitcall_sys_service_start = .;
    KEEP(*(.zinitcall.sys.service0.init))
    KEEP(*(.zinitcall.sys.service1.init))
    KEEP(*(.zinitcall.sys.service2.init))
    KEEP(*(.zinitcall.sys.service3.init))
    KEEP(*(.zinitcall.sys.service4.init))
    __zinitcall_sys_service_end = .;
    
    __zinitcall_sys_feature_start = .;
    KEEP(*(.zinitcall.sys.feature0.init))
    KEEP(*(.zinitcall.sys.feature1.init))
    KEEP(*(.zinitcall.sys.feature2.init))
    KEEP(*(.zinitcall.sys.feature3.init))
    KEEP(*(.zinitcall.sys.feature4.init))
    __zinitcall_sys_feature_end = .;
    
    __zinitcall_run_start = .;
    KEEP(*(.zinitcall.run0.init))
    KEEP(*(.zinitcall.run1.init))
    KEEP(*(.zinitcall.run2.init))
    KEEP(*(.zinitcall.run3.init))
    KEEP(*(.zinitcall.run4.init))
    __zinitcall_run_end = .;
    
    __zinitcall_app_service_start = .;
    KEEP(*(.zinitcall.app.service0.init))
    KEEP(*(.zinitcall.app.service1.init))
    KEEP(*(.zinitcall.app.service2.init))
    KEEP(*(.zinitcall.app.service3.init))
    KEEP(*(.zinitcall.app.service4.init))
    __zinitcall_app_service_end = .;
    
    __zinitcall_app_feature_start = .;
    KEEP(*(.zinitcall.app.feature0.init))
    KEEP(*(.zinitcall.app.feature1.init))
    KEEP(*(.zinitcall.app.feature2.init))
    KEEP(*(.zinitcall.app.feature3.init))
    KEEP(*(.zinitcall.app.feature4.init))
    __zinitcall_app_feature_end = .;
    
    __zinitcall_test_start = .;
    KEEP(*(.zinitcall.test0.init))
    KEEP(*(.zinitcall.test1.init))
    KEEP(*(.zinitcall.test2.init))
    KEEP(*(.zinitcall.test3.init))
    KEEP(*(.zinitcall.test4.init))
    __zinitcall_test_end = .;
    
    __zinitcall_exit_start = .;
    KEEP(*(.zinitcall.exit0.init))
    KEEP(*(.zinitcall.exit1.init))
    KEEP(*(.zinitcall.exit2.init))
    KEEP(*(.zinitcall.exit3.init))
    KEEP(*(.zinitcall.exit4.init))
    __zinitcall_exit_end = .;

SDK Task Initialization

The hardware abstraction layer must spawn the primary execution thread after completing low-level setup and kernel initialization. The following routine demonstrates the thread configuration and scheduler activation:

void FrameworkBootEntry(void)
{
    OsInitializeCoreFramework();
    printf("System initialization complete. Execution environment ready.\n");
}
 
int HardwareEntryPoint(VOID)
{
    PeripheralInitPhase(); 
    if (LOS_KernelInit() == LOS_OK) {
        TSK_INIT_PARAM_T threadConfig = {0};
        threadConfig.usTaskPrio = 14;
        threadConfig.pcName = "BootManager";
        threadConfig.pfnTaskEntry = (TSK_ENTRY_FUNC)FrameworkBootEntry;
        threadConfig.uwStackSize = 10240;
        UINT32 taskHandle = 0;
        
        if (LOS_TaskCreate(&taskHandle, &threadConfig) == LOS_OK) {
            LOS_Start();
        } else {
            printf("[ERROR] Thread creation failed.\n");
        }
    } else {
        printf("[FATAL] Kernel initialization unsuccessful.\n");
    }
    while (1);
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.