
固件操作系统嵌入式【免费下载链接】Atmosphere-stable大气层整合包系统稳定版项目地址https://gitcode.com/gh_mirrors/at/Atmosphere-stable点击查看免费下载本文围绕 Atmosphere大气层开源仓库中docs/components/modules/boot2.md所描述的 boot2 模块展开它是 Horizon OS 官方boot2系统模块的开源重实现核心职责是按依赖顺序启动系统其余所有必需的系统模块其独有增强是支持从 SD 卡启动用户自备的系统模块。阅读本文后你将掌握 boot2 在整条启动链路中的位置、两阶段启动编排的源码级细节以及如何通过boot2内容标志content flag让自己的程序随系统一起自启。boot2 在 Horizon 启动链路中的定位在 Horizon OS 中boot2是一个由 PMProcess Manager在开机后期代为拉起的关键系统模块。它本身不提供面向用户的 API而是作为启动编排器存在系统能否进入可用状态、SD 卡能否挂载、各类服务能否就绪都取决于 boot2 是否按正确顺序启动了其余模块。Atmosphere 对该模块进行了完整重实现工程位于 stratosphere/boot2。根据官方模块文档 docs/components/modules/boot2.mdAtmosphere 的 boot2 重实现与官方版本最大的差异在于它允许从 SD 卡启动用户提供的系统模块。这一能力正是 Atmosphere 各类自研系统模块如 ams_mitm、LogManager 等能够随系统一起被拉起的基础具体配置说明见 docs/features/configurations.md 的Content Specific Flags一节。从系统模块元数据 stratosphere/boot2/boot2.json 可以看到它的身份信息属性值说明nameboot2模块名称title_id0x0100000000000008固定系统模块 Title IDmain_thread_stack_size0x00004000主线程栈大小16 KBmain_thread_priority48主线程优先级default_cpu_id3默认运行于 CPU3service_accessfsp-srv、gpio、htc、lr、ncm、pm:bm、pm:shell、pm:info、set:sys可访问的服务列表filesystem_access.permissions0xFFFFFFFFFFFFFFFF全部文件系统权限可见 boot2 被授予了对 PM、NCM、FS、GPIO、设置服务等关键组件的访问权这正是它执行启动编排所需的全部权限面。模块入口与初始化极小堆上的启动准备boot2 的全部业务逻辑集中在单一源文件 stratosphere/boot2/source/boot2_main.cpp 中入口为ams::Main()void Main() { /* Set thread name. */ os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(boot2, Main)); AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) AMS_GET_SYSTEM_THREAD_PRIORITY(boot2, Main)); /* Launch all programs off of SYSTEM/the SD. */ boot2::LaunchPostSdCardBootPrograms(); }主线程只做两件事设置线程名并校验优先级然后立即调用boot2::LaunchPostSdCardBootPrograms()进入正式的启动编排。这印证了模块文档的定位——boot2 存在的唯一意义就是启动所有其他必要的系统模块。在InitializeSystemModule()阶段boot2 完成了极精简的启动准备从中可以直观看到它轻装上阵的设计void InitializeSystemModule() { /* Initialize heap. */ boot2::InitializeFsHeap(); /* Initialize our connection to sm. */ R_ABORT_UNLESS(sm::Initialize()); /* Initialize fs. */ fs::InitializeForSystem(); fs::SetAllocator(boot2::AllocateForFs, boot2::DeallocateForFs); fs::SetEnabledAutoAbort(false); /* Initialize other services we need. */ R_ABORT_UNLESS(pmbmInitialize()); R_ABORT_UNLESS(pminfoInitialize()); R_ABORT_UNLESS(pmshellInitialize()); R_ABORT_UNLESS(setsysInitialize()); gpio::Initialize(); ncm::Initialize(); /* Mount the SD card. */ R_ABORT_UNLESS(fs::MountSdCard(sdmc)); /* Verify that we can sanely execute. */ ams::CheckApiVersion(); }值得注意的细节包括极小堆设计为 FS 准备的堆只有2_KBg_fs_heap_memory[2_KB]通过lmem::CreateExpHeap创建并注册为 FS 的分配器fs::SetAllocator。boot2 刻意保持最小内存占用因为它只是过路模块完成编排后使命即告结束。依赖面收窄依次初始化sm、fs、pm:bm、pm:info、pm:shell、set:sys、gpio、ncm与 boot2.json 中service_access声明完全一一对应。挂载 SD 卡以挂载名sdmc挂载 SD 卡fs::MountSdCard(sdmc)随后才能扫描 SD 卡上的用户程序。API 版本校验ams::CheckApiVersion()用于确保 boot2 与当前运行环境匹配防止不兼容组合导致的启动异常。两阶段启动编排SD 卡就绪前与就绪后boot2 的编排逻辑被拆分为两个阶段分别位于 libraries/libstratosphere/source/boot2/boot2_api.board.nintendo_nx.cpp对应的公开 API 声明在 libraries/libstratosphere/include/stratosphere/boot2/boot2_api.hppAPI调用方职责LaunchPreSdCardBootProgramsAndBoot2()PM正常由 PM 调用拉起挂载 SD 卡所需的最少程序然后启动 boot2 本体LaunchPostSdCardBootPrograms()boot2正常由 boot2 调用SD 卡就绪后拉起其余全部系统模块与 SD 卡用户程序阶段一LaunchPreSdCardBootProgramsAndBoot2—— 由 PM 触发从源码结构看boot2 本身并非由系统固件直接拉起而是由 PM 在收到启动完成通知后触发。调用链位于 stratosphere/pm/source/impl/pm_process_manager.cpp 的NotifyBootFinished()中Result NotifyBootFinished() { ... boot2::LaunchPreSdCardBootProgramsAndBoot2(); s_has_boot_finished true; os::SignalSystemEvent(std::addressof(g_boot_finished_event)); ... }该函数内部遵循严格的依赖顺序等待 fsp-srv 的 mitm 安装完成sm::mitm::WaitMitm(sm::ServiceName::Encode(fsp-srv))源码注释明确指出希望这尽可能早发生以保证 FS 层从一开始就处于 Atmosphere 的管控之下。启动 SD 卡挂载所需的最少程序集合。源码中的PreSdCardLaunchPrograms[]常量数组给出了明确清单及其依赖关系/* psc, bus, pcv is the minimal set of required programs to get SD card. */ /* bus depends on pcie, and pcv depends on settings. */ constexpr const ncm::SystemProgramId PreSdCardLaunchPrograms[] { ncm::SystemProgramId::Psc, /* psc */ ncm::SystemProgramId::Pcie, /* pcie */ ncm::SystemProgramId::Bus, /* bus */ ncm::SystemProgramId::Settings, /* settings */ ncm::SystemProgramId::Pcv, /* pcv */ ncm::SystemProgramId::Usb, /* usb */ };这里有一处值得深究的工程细节在 9.0.0 及以上固件FS 挂载 SD 卡依赖 USB 系统模块已先启动IsUsbRequiredToMountSdCard()返回hos::GetVersion() hos::Version_9_0_0因此阶段一按固件版本决定是否提前拉起usb。 3.修复启动竞态在启动pcv之前boot2 通过setsysInitialize()主动连接set:sys并读取boot!force_maintenance设置项强制settings完成其数据库初始化规避一个已知的启动竞态条件。 4.等待其他 Atmosphere mitm 模块就绪等待set:sys的 mitm在 EristaTegra X1机型上还按固件版本等待bpc2.0.0 以上或bpc:c的 mitm。 5.最终以NcmStorageId_None强制从 SD 卡启动 boot2 本体/* Launch Atmosphere boot2, using NcmStorageId_None to force SD card boot. */ LaunchProgram(nullptr, ncm::ProgramLocation::Make(ncm::SystemProgramId::Boot2, ncm::StorageId::None), 0);使用StorageId::None意味着 boot2 程序文件从 SD 卡加载——这是 Atmosphere boot2 重实现能够接管启动编排的前提。阶段二LaunchPostSdCardBootPrograms—— boot2 本体的编排SD 卡就绪后boot2 进入第二阶段的全面编排按以下顺序推进补启 USB若当前固件不需要 USB 来挂载 SD 卡即 9.0.0 以下则在此处补启usb。激活系统 FS 内容存储ncm::ActivateFsContentStorage(fs::ContentStorageId::System)为后续从 SYSTEM 分区加载程序做准备。判定维护模式见下一节。检测并前置声明第三方 mitm 模块扫描 SD 卡上带标志的程序读取其mitm.lst通过sm::mitm::DeclareFutureMitm提前向服务管理器声明要劫持的服务。按配置分支启动调试/遥测组件条件启动内容atmosphere!enable_htc为真htc、cs、dmnt.gen2否则若atmosphere!enable_standalone_gdbstub为真dmnt.gen2、tma独立 gdbstub 模式否则默认dmnt、tma选择日志管理器若atmosphere!enable_log_manager或atmosphere!enable_htc为真则启动 Atmosphere 自研的AtmosphereLogManager来自 SD 卡StorageId::None否则启动任天堂原版LogManager。按维护模式选择附加程序列表AdditionalLaunchPrograms与AdditionalMaintenanceLaunchPrograms两个常量数组内容基本一致覆盖omm、am、nvservices、nvnflinger、vi、pgl、ns、hid、audio、wlan、bluetooth、bsdsockets、nifm、account、friends、nfc、jpegdec、capsrv、ssl、nim、bcat、erpt、es、pctl、btm、eupld、glue、npns、fatal、ro、profiler、sdb、olsc、ngc、ngct等维护模式下额外按固件版本决定是否拉起npns7.0.0 起维护模式也会启动 npns。固件版本兼容分支12.0.0 之前的固件由 boot2 额外负责启动grc与migration12.0.0 起该职责移交其他模块。最后启动 SD 卡上的用户程序LaunchFlaggedProgramsOnSdCard()即本文主题——从 SD 卡加载用户自备系统模块。源码注释还透露了一处 Atmosphere 的刻意取舍AdditionalLaunchPrograms中eclct被注释掉注释为 Skip launching error collection in Atmosphere to lessen telemetry.即跳过官方错误收集模块以减少遥测。维护模式按键组合与配置双重触发boot2 通过IsMaintenanceMode()决定以维护模式启动系统其判定逻辑来自 boot2_api.board.nintendo_nx.cppbool IsMaintenanceMode() { /* Contact set:sys, retrieve boot!force_maintenance. */ if (IsForceMaintenance()) { return true; } /* Contact GPIO, read plus/minus buttons. */ return GetGpioPadLow(gpio::DeviceCode_ButtonVolUp) GetGpioPadLow(gpio::DeviceCode_ButtonVolDn); }维护模式由两个条件触发配置强制settings::fwdbg::GetSettingsItemValue(..., boot, force_maintenance)读取设置项boot!force_maintenance默认值视为 1可通过 docs/features/configurations.md 所述的系统设置覆盖机制调整。按键组合通过 GPIO 会话gpio::OpenSessionSetDirection(Direction_Input)GetValue读取音量 与音量 - 两个按键同时按下GpioValue_Low表示按下。判定为维护模式后boot2 会调用pm::bm::SetMaintenanceBoot()通知 PM并改走AdditionalMaintenanceLaunchPrograms精简启动列表。核心增强从 SD 卡启动用户系统模块boot2 标志机制模块文档明确指出 Atmosphere boot2 重实现的核心价值是允许从 SD 卡启动用户提供的系统模块。该机制的实现分为前置声明与实际启动两步全部由 SD 卡文件系统驱动。扫描规则内容目录 十六进制程序 IDIterateOverFlaggedProgramsOnSdCard()定义了统一的扫描逻辑打开sdmc:/atmosphere/contents目录不存在则静默返回逐项读取目录条目仅当条目名为16 个十六进制字符2 * sizeof(ncm::ProgramId)且全部通过std::isxdigit校验时才视为合法的程序 ID 目录对合法目录调用cfg::HasContentSpecificFlag(program_id, boot2)检查标志。标志文件的实际路径由 libraries/libstratosphere/source/cfg/cfg_flags.board.nintendo_nx.inc 中的HasContentSpecificFlag决定bool HasContentSpecificFlag(ncm::ProgramId program_id, const char *flag) { char content_flag[fs::EntryNameLengthMax 1]; util::SNPrintf(content_flag, sizeof(content_flag) - 1, /atmosphere/contents/%016 PRIx64 /flags/%s.flag, program_id.value, flag); return HasFlagFile(content_flag); }即标志文件路径为/atmosphere/contents/16位十六进制ProgramID/flags/boot2.flag。这与 docs/features/configurations.md 中Content Specific Flags一节的说明完全一致在对应程序 ID 目录下放置flag_name.flag即可启用该程序的行为标志其中boot2标志的含义正是该程序应在 boot2 过程中被启动。启动前的去重校验LaunchFlaggedProgramsOnSdCard()在启动每个带标志程序前会通过pm::info::HasLaunchedBootProgram(program_id)确认该程序尚未被启动过避免重复拉起随后以ncm::ProgramLocation::Make(program_id, ncm::StorageId::None)从 SD 卡加载执行LaunchProgram。mitm.lst提前声明服务劫持为了让用户自备系统模块能够在sm完成服务分发前就登记自己的劫持服务boot2 实现了DetectAndDeclareFutureMitms()对每个带boot2标志的程序尝试读取sdmc:/atmosphere/contents/program_id/mitm.lst文件按行存放服务名每行一个18 个字符允许空行\r/\n均视为换行每个服务名通过sm::ServiceName::Encode编码后调用sm::mitm::DeclareFutureMitm(...)向sm前置声明未来会劫持该服务非法行超过服务名长度上限会触发AMS_ABORT_UNLESS断言失败。这就是 Atmosphere 大量 mitm 型系统模块如 fs_mitm、set_mitm 等能够在系统服务分发早期就接管对应服务的关键机制boot2 在编排阶段替它们完成了服务声明。典型应用SD 卡上带 boot2 标志的程序布局结合上述源码逻辑一个随 Atmosphere 启动的用户系统模块在 SD 卡上应具备如下布局假设程序 ID 为0000000000000012/atmosphere/contents/0000000000000012/ ├── exefs/ # 程序本体NRO 转 NSO 等 ├── flags/ │ └── boot2.flag # 空文件存在即表示boot2 阶段启动我 └── mitm.lst # 可选每行一个要劫持的服务名操作要点程序 ID 目录名必须恰好为 16 位十六进制大写字符否则会被扫描逻辑静默跳过boot2.flag为空文件其存在性即标志本身若程序需要劫持服务mitm.lst必须在 boot2 运行前就位因为声明动作发生在程序启动之前若程序已由系统或其他流程启动boot2 会通过HasLaunchedBootProgram跳过不会重复加载。启动错误处理与健壮性boot2 对启动过程中的关键异常采用快速失败策略保证问题在启动早期就暴露初始化阶段任何服务初始化失败均以R_ABORT_UNLESS中止LaunchProgram中对启动结果做了轻量校验仅断言不命中ResultOutOfResource、ResultOutOfMemory、ResultLimitReached三类资源型错误其余结果放行——这是有意的宽松策略避免个别模块启动失败阻断整个编排流程对版本敏感的逻辑如pgl仅在 10.0.0 启动、usb与grc/migration的版本分支全部以hos::GetVersion()运行时判定使同一份 boot2 二进制可跨固件版本工作。总结从 docs/components/modules/boot2.md 的定位出发结合 stratosphere/boot2/source/boot2_main.cpp、boot2_api.board.nintendo_nx.cpp、boot2.json 与 cfg_flags.board.nintendo_nx.inc 的源码实现可以得出对 boot2 模块的完整认识它是 Horizon boot2 的完整重实现以最小内存占用2 KB FS 堆在启动后期完成全部系统模块的依赖编排它由 PM 触发、分两阶段执行先以最少程序集psc/pcie/bus/settings/pcv9.0.0 起加usb打通 SD 卡再编排剩余全部模块它内置了维护模式、HTC/gdbstub、日志管理器替换、版本分支等大量工程决策并刻意跳过eclct以减少遥测它的核心增强是 SD 卡自定义系统模块加载通过/atmosphere/contents/program_id/flags/boot2.flag空标志文件即可让用户程序随系统启动配合mitm.lst可在启动早期完成服务劫持声明——这正是 Atmosphere 扩展生态自研系统模块、自定义服务等的启动基石。若要在 SD 卡上部署自己的系统模块只需按上文布局放置程序与标志文件并确保程序 ID 目录名符合 16 位十六进制格式即可若涉及服务劫持则需同时准备格式正确的mitm.lst。赞分享固件操作系统嵌入式【免费下载链接】Atmosphere-stable大气层整合包系统稳定版项目地址https://gitcode.com/gh_mirrors/at/Atmosphere-stable点击查看免费下载相关推荐Atmosphère boot2 模块解析用 boot2 标志从 SD 卡启动自定义系统模块Atmosphère boot2 模块解析用 boot2 标志从 SD 卡启动自定义系统模块 Atmosphère 是对任天堂 Switch 自制固件cus固件操作系统嵌入式系统编程ExpandableBottomBar迁移指南从旧版本平滑升级到最新版本的7个步骤ExpandableBottomBar迁移指南从旧版本平滑升级到最新版本的7个步骤 ExpandableBottomBar是一款功能强大的Android底部导UI组件移动开发Atmosphère stratosphère 层完全指南Horizon OS 系统级模块重实现与自定义系统模块架构解析Atmosphère stratosphère 层完全指南Horizon OS 系统级模块重实现与自定义系统模块架构解析 stratosphère平流层是固件操作系统嵌入式系统编程上一篇douyin-downloader 抖音去水印批量下载一条命令搬空博主主页下一篇英雄联盟游戏助手终极指南如何用Akari工具集提升200%游戏效率创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考