blob: 00d8342e3e6ad344b6bbd379ba39459b528d6d51 [file] [log] [blame]
<!--
Documentation/_templates/layout.html
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership. The
ASF licenses this file to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.
-->
<!DOCTYPE html>
<html class="writer-html5" lang="en">
<head>
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>NuttX Protected Build &mdash; NuttX latest documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css" />
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css" />
<link rel="stylesheet" type="text/css" href="../_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css" />
<link rel="stylesheet" type="text/css" href="../_static/custom.css" />
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<script src="../_static/jquery.js"></script>
<script src="../_static/_sphinx_javascript_frameworks_compat.js"></script>
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<script src="../_static/clipboard.min.js"></script>
<script src="../_static/copybutton.js"></script>
<script src="../_static/design-tabs.js"></script>
<script src="../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Platform Directories" href="platform_directories.html" />
<link rel="prev" title="Integrating with Newlib" href="integrate_newlib.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="../index.html" class="icon icon-home"> NuttX
</a>
<!-- this version selector is quite ugly, should be probably replaced by something
more modern -->
<div class="version-selector">
<select onchange="javascript:location.href = this.value;">
<option value="../../latest" selected="selected">latest</option>
<option value="../../10.0.0" >10.0.0</option>
<option value="../../10.0.1" >10.0.1</option>
<option value="../../10.1.0" >10.1.0</option>
<option value="../../10.2.0" >10.2.0</option>
<option value="../../10.3.0" >10.3.0</option>
<option value="../../11.0.0" >11.0.0</option>
<option value="../../12.0.0" >12.0.0</option>
<option value="../../12.1.0" >12.1.0</option>
<option value="../../12.2.0" >12.2.0</option>
<option value="../../12.2.1" >12.2.1</option>
<option value="../../12.3.0" >12.3.0</option>
<option value="../../12.4.0" >12.4.0</option>
<option value="../../12.5.0" >12.5.0</option>
<option value="../../12.5.1" >12.5.1</option>
<option value="../../12.6.0" >12.6.0</option>
<option value="../../12.7.0" >12.7.0</option>
<option value="../../12.8.0" >12.8.0</option>
<option value="../../12.9.0" >12.9.0</option>
<option value="../../12.10.0" >12.10.0</option>
<option value="../../12.11.0" >12.11.0</option>
</select>
</div>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Table of Contents</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../index.html">Home</a></li>
<li class="toctree-l1"><a class="reference internal" href="../introduction/index.html">Introduction</a></li>
<li class="toctree-l1"><a class="reference internal" href="../quickstart/index.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="../contributing/index.html">Contributing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../introduction/inviolables.html">The Inviolable Principles of NuttX</a></li>
<li class="toctree-l1"><a class="reference internal" href="../platforms/index.html">Supported Platforms</a></li>
<li class="toctree-l1"><a class="reference internal" href="../components/index.html">OS Components</a></li>
<li class="toctree-l1"><a class="reference internal" href="../applications/index.html">Applications</a></li>
<li class="toctree-l1"><a class="reference internal" href="../implementation/index.html">Implementation Details</a></li>
<li class="toctree-l1"><a class="reference internal" href="../reference/index.html">API Reference</a></li>
<li class="toctree-l1"><a class="reference internal" href="../faq/index.html">FAQ</a></li>
<li class="toctree-l1"><a class="reference internal" href="../debugging/index.html">Debugging</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Guides</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="nfs.html">NFS Client How-To</a></li>
<li class="toctree-l2"><a class="reference internal" href="usbtrace.html">USB Device Trace</a></li>
<li class="toctree-l2"><a class="reference internal" href="simulator.html">Simulator</a></li>
<li class="toctree-l2"><a class="reference internal" href="rndis.html">How to use RNDIS</a></li>
<li class="toctree-l2"><a class="reference internal" href="drivers.html">Drivers</a></li>
<li class="toctree-l2"><a class="reference internal" href="cpp_cmake.html">C++ Example using CMake</a></li>
<li class="toctree-l2"><a class="reference internal" href="pysimcoder.html">pysimCoder integration with NuttX</a></li>
<li class="toctree-l2"><a class="reference internal" href="customboards.html">Custom Boards How-To</a></li>
<li class="toctree-l2"><a class="reference internal" href="customapps.html">Custom Apps How-to</a></li>
<li class="toctree-l2"><a class="reference internal" href="citests.html">Running CI Test Locally</a></li>
<li class="toctree-l2"><a class="reference internal" href="zerolatencyinterrupts.html">High Performance: Zero Latency Interrupts, Maskable Nested Interrupts</a></li>
<li class="toctree-l2"><a class="reference internal" href="fortify.html">Fortify</a></li>
<li class="toctree-l2"><a class="reference internal" href="nestedinterrupts.html">Nested Interrupts</a></li>
<li class="toctree-l2"><a class="reference internal" href="ofloader.html">Open Flash Loader</a></li>
<li class="toctree-l2"><a class="reference internal" href="testingtcpip.html">Testing TCP/IP Network Stacks</a></li>
<li class="toctree-l2"><a class="reference internal" href="automounter.html">Auto-Mounter</a></li>
<li class="toctree-l2"><a class="reference internal" href="stm32nullpointer.html">STM32 Null Pointer Detection</a></li>
<li class="toctree-l2"><a class="reference internal" href="stm32ccm.html">STM32 CCM Allocator</a></li>
<li class="toctree-l2"><a class="reference internal" href="etcromfs.html">etc romfs</a></li>
<li class="toctree-l2"><a class="reference internal" href="thread_local_storage.html">Thread Local Storage</a></li>
<li class="toctree-l2"><a class="reference internal" href="devicetree.html">Device Tree</a></li>
<li class="toctree-l2"><a class="reference internal" href="changing_systemclockconfig.html">Changing the System Clock Configuration</a></li>
<li class="toctree-l2"><a class="reference internal" href="usingkernelthreads.html">Using Kernel Threads</a></li>
<li class="toctree-l2"><a class="reference internal" href="armv7m_runtimestackcheck.html">ARMv7-M Run Time Stack Checking</a></li>
<li class="toctree-l2"><a class="reference internal" href="include_files_board_h.html">Including Files in board.h</a></li>
<li class="toctree-l2"><a class="reference internal" href="specialstuff_in_nuttxheaderfiles.html">Why can’t I put my special stuff in NuttX header files?</a></li>
<li class="toctree-l2"><a class="reference internal" href="kernel_threads_with_custom_stacks.html">Kernel Threads with Custom Stacks</a></li>
<li class="toctree-l2"><a class="reference internal" href="versioning_and_task_names.html">Versioning and Task Names</a></li>
<li class="toctree-l2"><a class="reference internal" href="logging_rambuffer.html">Logging to a RAM Buffer</a></li>
<li class="toctree-l2"><a class="reference internal" href="ipv6.html">IPv6</a></li>
<li class="toctree-l2"><a class="reference internal" href="integrate_newlib.html">Integrating with Newlib</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">NuttX Protected Build</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#the-traditional-flat-build">The Traditional “Flat” Build</a></li>
<li class="toctree-l3"><a class="reference internal" href="#the-two-pass-protected-build">The “Two Pass” Protected Build</a></li>
<li class="toctree-l3"><a class="reference internal" href="#the-memory-protection-unit">The Memory Protection Unit</a></li>
<li class="toctree-l3"><a class="reference internal" href="#advantages-of-the-protected-build">Advantages of the Protected Build</a></li>
<li class="toctree-l3"><a class="reference internal" href="#user-space-proxies-kernel-space-stubs">User-Space Proxies/Kernel-Space Stubs</a></li>
<li class="toctree-l3"><a class="reference internal" href="#combining-intel-hex-files">Combining Intel HEX Files</a></li>
<li class="toctree-l3"><a class="reference internal" href="#files-and-directories">Files and Directories</a></li>
<li class="toctree-l3"><a class="reference internal" href="#alignment-regions-and-subregions">Alignment, Regions, and Subregions</a></li>
<li class="toctree-l3"><a class="reference internal" href="#memory-management">Memory Management</a><ul>
<li class="toctree-l4"><a class="reference internal" href="#single-user-heap">Single User Heap</a></li>
<li class="toctree-l4"><a class="reference internal" href="#dual-partitioned-heaps">Dual, Partitioned Heaps</a></li>
<li class="toctree-l4"><a class="reference internal" href="#the-traditional-approach">The Traditional Approach</a></li>
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="#comparing-the-flat-build-configuration-with-the-protected-build-configuration">Comparing the “Flat” Build Configuration with the Protected Build Configuration</a></li>
<li class="toctree-l3"><a class="reference internal" href="#size-expansion">Size Expansion</a></li>
<li class="toctree-l3"><a class="reference internal" href="#performance-issues">Performance Issues</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="platform_directories.html">Platform Directories</a></li>
<li class="toctree-l2"><a class="reference internal" href="port_drivers_to_stm32f7.html">Porting Drivers to the STM32 F7</a></li>
<li class="toctree-l2"><a class="reference internal" href="semihosting.html">Semihosting</a></li>
<li class="toctree-l2"><a class="reference internal" href="renode.html">Run NuttX on Renode</a></li>
<li class="toctree-l2"><a class="reference internal" href="signal_events_interrupt_handlers.html">Signaling Events from Interrupt Handlers</a></li>
<li class="toctree-l2"><a class="reference internal" href="signaling_sem_priority_inheritance.html">Signaling Semaphores and Priority Inheritance</a></li>
<li class="toctree-l2"><a class="reference internal" href="smaller_vector_tables.html">Smaller Vector Tables</a></li>
<li class="toctree-l2"><a class="reference internal" href="port.html">How to port</a></li>
<li class="toctree-l2"><a class="reference internal" href="updating_release_system_elf.html">Updating a Release System with ELF Programs</a></li>
<li class="toctree-l2"><a class="reference internal" href="partially_linked_elf.html">ELF Programs – With Symbol Tables</a></li>
<li class="toctree-l2"><a class="reference internal" href="fully_linked_elf.html">ELF Programs – No Symbol Tables</a></li>
<li class="toctree-l2"><a class="reference internal" href="building_nuttx_with_app_out_of_src_tree.html">Building NuttX with Applications Outside the Source Tree</a></li>
<li class="toctree-l2"><a class="reference internal" href="building_uclibcpp.html">Building uClibc++</a></li>
<li class="toctree-l2"><a class="reference internal" href="custom_app_directories.html">Custom Application Directories</a></li>
<li class="toctree-l2"><a class="reference internal" href="multiple_nsh_sessions.html">Multiple NSH Sessions</a></li>
<li class="toctree-l2"><a class="reference internal" href="nsh_network_link_management.html">NSH Network Link Management</a></li>
<li class="toctree-l2"><a class="reference internal" href="ram_rom_disks.html">RAM Disks and ROM Disks</a></li>
<li class="toctree-l2"><a class="reference internal" href="reading_can_msgs.html">Reading CAN Messages</a></li>
<li class="toctree-l2"><a class="reference internal" href="remove_device_drivers_nsh.html">Removing Device Drivers with NSH</a></li>
<li class="toctree-l2"><a class="reference internal" href="rust.html">Rust in NuttX</a></li>
<li class="toctree-l2"><a class="reference internal" href="optee.html">Interfacing with OP-TEE</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../glossary.html">Glossary</a></li>
<li class="toctree-l1"><a class="reference internal" href="../logos/index.html">NuttX Logos</a></li>
<li class="toctree-l1"><a class="reference internal" href="../_tags/tagsindex.html">Tags</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../index.html">NuttX</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="../index.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item"><a href="index.html">Guides</a></li>
<li class="breadcrumb-item active">NuttX Protected Build</li>
<li class="wy-breadcrumbs-aside">
<a href="https://github.com/apache/nuttx/blob/master/Documentation/guides/protected_build.rst" class="fa fa-github"> Edit on GitHub</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<section id="nuttx-protected-build">
<h1>NuttX Protected Build<a class="headerlink" href="#nuttx-protected-build" title="Permalink to this heading"></a></h1>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Migrated from :
<a class="reference external" href="https://cwiki.apache.org/confluence/display/NUTTX/NuttX+Protected+Build">https://cwiki.apache.org/confluence/display/NUTTX/NuttX+Protected+Build</a></p>
</div>
<section id="the-traditional-flat-build">
<h2>The Traditional “Flat” Build<a class="headerlink" href="#the-traditional-flat-build" title="Permalink to this heading"></a></h2>
<p>The traditional NuttX build is a “flat” build. By flat, I mean that when
you build NuttX, you end up with a single “blob” called <code class="docutils literal notranslate"><span class="pre">nuttx</span></code>. All of the
components of the build reside in the same address space. All components
of the build can access all other components of the build.</p>
</section>
<section id="the-two-pass-protected-build">
<h2>The “Two Pass” Protected Build<a class="headerlink" href="#the-two-pass-protected-build" title="Permalink to this heading"></a></h2>
<p>The NuttX protected build, on the other hand, is a “two-pass” build and
generates two “blobs”: (1) a separately compiled and linked <cite>kernel</cite> blob
called, again, <cite>nuttx</cite> and separately compiled and linked <cite>user</cite> blob called
in <code class="docutils literal notranslate"><span class="pre">nuttx_user.elf</span></code> (in the existing build configurations). The user blob
is created on pass 1 and the kernel blob is created on pass2.</p>
<p>These two make commands are identical:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>make
make<span class="w"> </span>pass1<span class="w"> </span>pass2
</pre></div>
</div>
<p>But the second is clearer and I prefer to use it for the protected build.
In the second case, the user and kernel blobs are built separately; in the
first, the kernel and user blob builds may be intermixed and somewhat
confusing. You can also build the kernel and user blobs separately with
one of the following commands:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>make<span class="w"> </span>pass1
make<span class="w"> </span>pass2
</pre></div>
</div>
<p>At the end of the build, there will be several files in the top-level NuttX build directory. From Pass 1:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">nuttx_user.elf</span></code>. The pass1 user-space ELF file</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">nuttx_user.hex</span></code>. The pass1 Intel HEX format file (selected in <code class="docutils literal notranslate"><span class="pre">defconfig</span></code>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">User.map</span></code>. Symbols in the user-space ELF file</p></li>
</ul>
<p>From Pass 2:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">nuttx</span></code>. The pass2 kernel-space ELF file</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">nuttx.hex</span></code>. The pass2 Intel HEX file (selected in <code class="docutils literal notranslate"><span class="pre">defconfig</span></code>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">System.map</span></code>. Symbols in the kernel-space ELF file</p></li>
</ul>
</section>
<section id="the-memory-protection-unit">
<h2>The Memory Protection Unit<a class="headerlink" href="#the-memory-protection-unit" title="Permalink to this heading"></a></h2>
<p>If the MCU supports a Memory Protection Unit (MPU), then the logic within
the kernel blob all execute in kernel-mode, i.e., with all privileges.
These privileged threads can access all memory, all CPU instructions,
and all MCU registers. The logic executing within the user-mode blob,
on the other hand, all execute in user-mode with certain restrictions
as enforced by the MCU and by the MPU. The MCU may restrict access to
certain registers and machine instructions; with the MPU, access to all
kernel memory resources are prohibited from the user logic. This includes
the kernel blob’s FLASH, .bss/.data storage, and the kernel heap memory.</p>
</section>
<section id="advantages-of-the-protected-build">
<h2>Advantages of the Protected Build<a class="headerlink" href="#advantages-of-the-protected-build" title="Permalink to this heading"></a></h2>
<p>The advantages of such a protected build are (1) security and (2)
modularity. Since the kernel resources are protected, it will be much
less likely that a misbehaving task will crash the system or that a
wild pointer access will corrupt critical memory. This security also
provides a safer environment in which to execute 3rd party software
and prevents “snooping” into the kernel memory from the hosted applications.</p>
<p>Modularity is assured because there is a strict control of the exposed
kernel interfaces. In the flat build, all symbols are exposed and there
is no enforcement of a kernel API. With the protected build, on the
other hand, all interactions with the kernel from the user application
logic must use <cite>system calls</cite> (or <cite>syscalls</cite>) to interface with the OS. A
system call is necessary to transition from user-mode to kernel-mode;
all user-space operating system interfaces are via syscall <cite>proxies</cite>.
Then, while in kernel mode, the kernel system call handler will
perform the OS service requested by the application. At the
conclusion of system processing, user-privileges are restored
and control is return to the user application. Since the only
interactions with the kernel can be through support system calls,
modularity of the OS is guaranteed.</p>
</section>
<section id="user-space-proxies-kernel-space-stubs">
<h2>User-Space Proxies/Kernel-Space Stubs<a class="headerlink" href="#user-space-proxies-kernel-space-stubs" title="Permalink to this heading"></a></h2>
<p>The same OS interfaces are exposed to the application in both the “flat”
build and the protected build. The difference is that in the protected
build, the user-code interfaces with a <cite>proxy</cite> for the OS function. For
example, here is what a proxy for the OS <code class="docutils literal notranslate"><span class="pre">getpid()</span></code> interface:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;unistd.h&gt;</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;syscall.h&gt;</span>
<span class="kt">pid_t</span><span class="w"> </span><span class="nf">getpid</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">(</span><span class="kt">pid_t</span><span class="p">)</span><span class="n">sys_call0</span><span class="p">(</span><span class="n">SYS_getpid</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Thus the <code class="docutils literal notranslate"><span class="pre">getpid()</span></code> proxy is a stand-in for the real OS <code class="docutils literal notranslate"><span class="pre">getpid()</span></code> interface
that executes a system call so the kernel code can perform the real
<code class="docutils literal notranslate"><span class="pre">getpid()</span></code> operation on behalf of the user application. Proxies are
auto-generated for all exported OS interfaces using the CSV file
<code class="docutils literal notranslate"><span class="pre">syscall/syscall.csv</span></code> and the program <code class="docutils literal notranslate"><span class="pre">tools/mksyscalls</span></code>. Similarly,
on the kernel-side, there are auto-generated <cite>stubs</cite> that map the
system calls back into real OS calls. These, however, are internal
to the OS and the implementation may be architecture-specific.
See the <code class="docutils literal notranslate"><span class="pre">README.txt</span></code> files in those directories for further information.</p>
</section>
<section id="combining-intel-hex-files">
<h2>Combining Intel HEX Files<a class="headerlink" href="#combining-intel-hex-files" title="Permalink to this heading"></a></h2>
<p>One issue that you may face is that the two pass builds creates two
FLASH images. Some debuggers that I use will allow me to write each
image to FLASH separately. Others will expect to have a single Intel
HEX image. In this latter case, you may need to combine the two Intel
HEX files into one. Here is how you can do that:</p>
<ol class="arabic simple">
<li><p>The <cite>tail</cite> of the <code class="docutils literal notranslate"><span class="pre">nuttx.hex</span></code> file should look something like this
(with my comments and spaces added):</p></li>
</ol>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$<span class="w"> </span>tail<span class="w"> </span>nuttx.hex
<span class="c1"># 00, data records</span>
...
:10<span class="w"> </span>9DC0<span class="w"> </span><span class="m">00</span><span class="w"> </span>01000000000800006400020100001F0004
:10<span class="w"> </span>9DD0<span class="w"> </span><span class="m">00</span><span class="w"> </span>3B005A0078009700B500D400F300110151
:08<span class="w"> </span>9DE0<span class="w"> </span><span class="m">00</span><span class="w"> </span>30014E016D0100008D
<span class="c1"># 05, Start Linear Address Record</span>
:04<span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">05</span><span class="w"> </span><span class="m">0800</span><span class="w"> </span><span class="m">0419</span><span class="w"> </span>D2
<span class="c1"># 01, End Of File record</span>
:00<span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">01</span><span class="w"> </span>FF
</pre></div>
</div>
<p>Use an editor such as vi to remove the 05 and 01 records.</p>
<ol class="arabic simple" start="2">
<li><p>The <cite>head</cite> of the <code class="docutils literal notranslate"><span class="pre">nuttx_user.hex</span></code> file should look something like this
(again with my comments and spaces added):</p></li>
</ol>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$<span class="w"> </span>head<span class="w"> </span>nuttx_user.hex
<span class="c1"># 04, Extended Linear Address Record</span>
:02<span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">04</span><span class="w"> </span><span class="m">0801</span><span class="w"> </span>F1
<span class="c1"># 00, data records</span>
:10<span class="w"> </span><span class="m">8000</span><span class="w"> </span><span class="m">00</span><span class="w"> </span>BD89<span class="w"> </span>01084C800108C8110208D01102087E
:10<span class="w"> </span><span class="m">8010</span><span class="w"> </span><span class="m">00</span><span class="w"> </span><span class="m">0010</span><span class="w"> </span>00201C1000201C1000203C16002026
:10<span class="w"> </span><span class="m">8020</span><span class="w"> </span><span class="m">00</span><span class="w"> </span>4D80<span class="w"> </span>01085D80010869800108ED83010829
...
</pre></div>
</div>
<p>Nothing needs to be done here. The <code class="docutils literal notranslate"><span class="pre">nuttx_user.hex</span></code> file should be fine.</p>
<ol class="arabic simple" start="3">
<li><p>Combine the edited nuttx.hex and un-edited <code class="docutils literal notranslate"><span class="pre">nuttx_user.hex</span></code> file to produce
a single combined hex file:</p></li>
</ol>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$<span class="w"> </span>cat<span class="w"> </span>nuttx.hex<span class="w"> </span>nuttx_user.hex<span class="w"> </span>&gt;combined.hex
</pre></div>
</div>
<p>Then use the <code class="docutils literal notranslate"><span class="pre">combined.hex</span></code> file with for FLASH/JTAG tool. If you do this
a lot, you will probably want to invest a little time to develop a tool
to automate these steps.</p>
</section>
<section id="files-and-directories">
<h2>Files and Directories<a class="headerlink" href="#files-and-directories" title="Permalink to this heading"></a></h2>
<p>Here is a summary of directories and files used by the STM32F4Discovery
protected build:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">boards/arm/stm32/stm32f4discovery/configs/kostest</span></code>. This is the kernel
mode OS test configuration. The two standard configuration files
can be found in this directory: (1) <code class="docutils literal notranslate"><span class="pre">defconfig</span></code> and (2) <code class="docutils literal notranslate"><span class="pre">Make.defs</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">boards/arm/stm32/stm32f4discovery/kernel</span></code>. This is the first past
build directory. The Makefile in this directory is invoked to
produce the pass1 object (<code class="docutils literal notranslate"><span class="pre">nuttx_user.elf</span></code> in this case). The
second pass object is created by <code class="docutils literal notranslate"><span class="pre">arch/arm/src/Makefile</span></code>. Also
in this directory is the file <code class="docutils literal notranslate"><span class="pre">userspace.c</span></code>. The user-mode blob
contains a header that includes information need by the kernel
blob in order to interface with the user-code. That header is
defined in by this file.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">boards/arm/stm32/stm32f4discovery/scripts</span></code>. Linker scripts for
the kernel mode build are found in this directory. This includes
(1) <code class="docutils literal notranslate"><span class="pre">memory.ld</span></code> which hold the common memory map, (2) <code class="docutils literal notranslate"><span class="pre">user-space.ld</span></code>
that is used for linking the pass1 user-mode blob, and (3)
<code class="docutils literal notranslate"><span class="pre">kernel-space.ld</span></code> that is used for linking the pass1 kernel-mode blob.</p></li>
</ul>
</section>
<section id="alignment-regions-and-subregions">
<h2>Alignment, Regions, and Subregions<a class="headerlink" href="#alignment-regions-and-subregions" title="Permalink to this heading"></a></h2>
<p>There are some important comments in the <code class="docutils literal notranslate"><span class="pre">memory.ld</span></code>
file that are worth duplicating here:</p>
<p>“The STM32F407VG has 1024Kb of FLASH beginning at address
0x0800:0000 and 192Kb of SRAM. SRAM is split up into three blocks:</p>
<ul class="simple">
<li><p>“112KB of SRAM beginning at address 0x2000:0000</p></li>
<li><p>“16KB of SRAM beginning at address 0x2001:c000</p></li>
<li><p>“64KB of CCM SRAM beginning at address 0x1000:0000</p></li>
</ul>
<p>“When booting from FLASH, FLASH memory is aliased to address
0x0000:0000 where the code expects to begin execution by jumping
to the entry point in the 0x0800:0000 address range.</p>
<p>“For MPU support, the kernel-mode NuttX section is assumed to
be 128Kb of FLASH and 4Kb of SRAM. That is an excessive amount
for the kernel which should fit into 64KB and, of course, can
be optimized as needed… Allowing the additional memory does
permit addition debug instrumentation to be added to the kernel
space without overflowing the partition.</p>
<p>“Alignment of the user space FLASH partition is also a critical
factor: The user space FLASH partition will be spanned with a
single region of size 2||n bytes. The alignment of the user-space
region must be the same. As a consequence, as the user-space
increases in size, the alignment requirement also increases.</p>
<p>“This alignment requirement means that the largest user space
FLASH region you can have will be 512KB at it would have to be
positioned at 0x08800000. If you change this address, don’t
forget to change the <code class="docutils literal notranslate"><span class="pre">CONFIG_NUTTX_USERSPACE</span></code> configuration
setting to match and to modify the check in <code class="docutils literal notranslate"><span class="pre">kernel/userspace.c</span></code>.</p>
<p>“For the same reasons, the maximum size of the SRAM mapping is
limited to 4KB. Both of these alignment limitations could be
reduced by using multiple MPU regions to map the FLASH/SDRAM
range or perhaps with some clever use of subregions.”</p>
</section>
<section id="memory-management">
<h2>Memory Management<a class="headerlink" href="#memory-management" title="Permalink to this heading"></a></h2>
<p>At present, there are two options for memory management in the
NuttX protected build:</p>
<section id="single-user-heap">
<h3>Single User Heap<a class="headerlink" href="#single-user-heap" title="Permalink to this heading"></a></h3>
<p>By default, there is only a single user-space heap and heap
allocator that is shared by both kernel- and user-modes.
PROs: Simple and makes good use of the heap memory space,
CONs: Awkward architecture and no security for kernel-mode
allocations.</p>
</section>
<section id="dual-partitioned-heaps">
<h3>Dual, Partitioned Heaps<a class="headerlink" href="#dual-partitioned-heaps" title="Permalink to this heading"></a></h3>
<p>Two configuration options can change this behavior:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_MM_MULTIHEAP=y</span></code>. This changes internal memory manager interfaces
so that multiple heaps can be supported.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_MM_KERNEL_HEAP=y</span></code>. Uses the multi-heap capability to enable
a kernel heap</p></li>
</ul>
<p>If this both options are defined defined, the two heap partitions and
two copies of the memory allocators are built:</p>
<p>One un-protected heap partition that will allocate user accessible memory
that is shared by both the kernel- and user-space code. That allocator
physically resides in the user address space so that it can be called
directly by both the user- and kernel-space code. There is a header at
the beginning of the user-space blob; the kernel-space code gets
address of the user-space allocator from this header.</p>
<p>And another protected heap partition that will allocate protected
memory that is only accessible from the kernel code. This allocator
is built into the kernel block. This separate protected heap is
required if you want to support security features.</p>
<p>NOTE: There are security issues with calling into the user space
allocators in kernel mode. That is a security hole that could be
exploit to gain control of the system! Instead, the kernel code
should switch to user mode before entering the memory allocator
stubs (perhaps via a trap). The memory allocator stubs should
then trap to return to kernel mode (as does the signal handler now).</p>
</section>
<section id="the-traditional-approach">
<h3>The Traditional Approach<a class="headerlink" href="#the-traditional-approach" title="Permalink to this heading"></a></h3>
<p>A more traditional approach would use something like the interface
<code class="docutils literal notranslate"><span class="pre">sbrk()</span></code>. The <code class="docutils literal notranslate"><span class="pre">sbrk()</span></code> function adds memory to the heap space
allocation of the calling process. In this case, there would
still be kernel- and user-mode instances of the memory allocators.
Each would <code class="docutils literal notranslate"><span class="pre">sbrk()</span></code> as necessary to extend their heap; the pages
allocated for the kernel-mode allocator would be protected but
the pages allocated for the user-mode allocator would not.
PROs: Meets all of the needs. CONs: Complex. Memory losses
due to quantization.</p>
<p>This approach works well with CPUs that have very capable
Memory Management Units (MMUs) that can coalesce the
srbk-ed chunks to a contiguous, <cite>virtual</cite> heap region.
Without an MMU, the sbrk-ed memory would not be
contiguous; this would limit the sizes of allocations
due to the physical pages.</p>
<p>Many MCUs will have Memory Protection Units (MPUs) that can
support the security features (only). However these lower
end MPUs may not support sufficient mapping capability to
support this traditional approach. The ARMv7-M MPU, for
example, only supports eight protection regions to manage
all FLASH and SRAM and so this approach would not be
technically feasible for th ARMv7-M family (Cortex-M3/4).</p>
</section>
</section>
<section id="comparing-the-flat-build-configuration-with-the-protected-build-configuration">
<h2>Comparing the “Flat” Build Configuration with the Protected Build Configuration<a class="headerlink" href="#comparing-the-flat-build-configuration-with-the-protected-build-configuration" title="Permalink to this heading"></a></h2>
<p>Compare, for example the configuration
<code class="docutils literal notranslate"><span class="pre">boards/arm/stm32/stm32f4discovery/configs/ostest</span></code> and the
configuration <code class="docutils literal notranslate"><span class="pre">boards/arm/stm32/stm32f4discovery/configs/kostest</span></code>.
These two configurations are identical except that one builds a
“flat” version of OS test and the other builds a kernel version
of the OS test. See the file <code class="docutils literal notranslate"><span class="pre">boards/arm/stm32/stm32f4discovery/README.txt</span></code>
for more details about those configurations.</p>
<p>The configurations can be compared using the <code class="docutils literal notranslate"><span class="pre">cmpconfig</span></code> tool:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nb">cd</span><span class="w"> </span>tools
make<span class="w"> </span>-f<span class="w"> </span>Makefile.host<span class="w"> </span>cmpconfig
<span class="nb">cd</span><span class="w"> </span>..
tools/cmpconfig<span class="w"> </span>boards/arm/stm32/stm32f4discovery/configs/ostest/defconfig<span class="w"> </span>boards/arm/stm32/stm32f4discovery/configs/kostest/defconfig
</pre></div>
</div>
<p>Here is a summary of the meaning of all of the important differences in the
configurations. This should be enough information for you to convert any
configuration from a “flat” to a protected build:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_BUILD_2PASS=y</span></code>. This enables the two pass build.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_BUILD_PROTECTED=y</span></code>. This option enables the “two pass”
protected build.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_PASS1_BUILDIR=&quot;boards/arm/stm32/stm32f4discovery/kernel&quot;</span></code>.
This tells the build system the (relative) location of the pass1 build directory.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_PASS1_OBJECT=&quot;&quot;</span></code>. In some “two pass” build configurations,
the build system need to know the name of the first pass object.
This setting is not used for the protected build.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_NUTTX_USERSPACE=0x08020000</span></code>. This is the expected location
where the user-mode blob will be located. The user-mode blob
contains a header that includes information need by the kernel
blob in order to interface with the user-code. That header will
be expected to reside at this location.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_PASS1_TARGET=&quot;all&quot;</span></code>. This is the build target to use for
invoking the pass1 make.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_MM_MULTIHEAP=y</span></code>. This changes internal memory manager
interfaces so that multiple heaps can be supported.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_MM_KERNEL_HEAP=y</span></code>. NuttX supports the option of using a
single user-accessible heap or, if this options is defined,
two heaps: (1) one that will allocate user accessible memory
that is shared by both the kernel- and user-space code, and
(2) one that will allocate protected memory that is only
accessible from the kernel code. Separate heap memory is required
if you want to support security features.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_MM_KERNEL_HEAPSIZE=8192</span></code>. This determines an approximate
size for the kernel heap. The standard heap space is partitioned
into a kernel- and user-heap space. This size of the kernel heap
is only approximate because the user heap is subject to stringent
alignment requirements. Because of the alignment requirements, the
actual size of the kernel heap could be considerable larger than this.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_BOARD_EARLY_INITIALIZE=y</span></code>. This setting enables a special,
<cite>early</cite> initialization call to initialize board-specific resources.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_BOARD_LATE_INITIALIZE=y</span></code>. This setting enables a special
initialization call to initialize <cite>late</cite> board-specific resources.
The difference between <code class="docutils literal notranslate"><span class="pre">CONFIG_BOARD_EARLY_INITIALIZE</span></code> and
<code class="docutils literal notranslate"><span class="pre">CONFIG_BOARD_LATE_INITIALIZE</span></code> is that the <code class="docutils literal notranslate"><span class="pre">CONFIG_BOARD_EARLY_INITIALIZE</span></code>
logic runs earlier in initialization before the full operating
system is up and running. <code class="docutils literal notranslate"><span class="pre">CONFIG_BOARD_LATE_INITIALIZE</span></code>, on the
other hand, runs at the completion of initialization, just before
the user applications are started. Neither <code class="docutils literal notranslate"><span class="pre">CONFIG_BOARD_EARLY_INITIALIZE</span></code>
nor <code class="docutils literal notranslate"><span class="pre">CONFIG_BOARD_LATE_INITIALIZE</span></code> are used in the OS test
configuration but other configurations (such as NSH)
require some application-specific initialization before
the application can run. In the “flat” build, such initialization
is performed as part of the application start-up sequence.
These includes such things as initializing device drivers.
These same initialization steps must be performed in kernel
mode for the protected build and <code class="docutils literal notranslate"><span class="pre">CONFIG_BOARD_LATE_INITIALIZE</span></code>.
See <code class="docutils literal notranslate"><span class="pre">boards/arm/stm32/stm32f4discovery/src/up_boot.c</span></code> for an
example of such board initialization code.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_NSH_ARCHINITIALIZE</span></code> is not defined. The setting
<code class="docutils literal notranslate"><span class="pre">CONFIG_NSH_ARCHINITIALIZE</span></code> does not apply to the OS test
configuration, however, this is noted here as an example
of initialization that cannot be performed in the protected build.</p></li>
</ul>
<p>Architecture-Specific Options:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_SYS_RESERVED=8</span></code>. The user application logic
interfaces with the kernel blob using system calls.
The architecture-specific logic may need to reserved a
few system calls for its own internal use. The ARMv7-M
architectures all require 8 reserved system calls.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_SYS_NNEST=2</span></code>. System calls may be nested. The
system must retain information about each nested system
call and this setting is used to set aside resources for
nested system calls. In the current architecture, a maximum
nesting level of two is all that is needed.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_ARMV7M_MPU=y</span></code>. This settings enables support for
the ARMv7-M Memory Protection Unit (MPU). The MPU is used
to prohibit user-mode access to kernel resources.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">CONFIG_ARMV7M_MPU_NREGIONS=8</span></code>. The ARMv7-M MPU supports 8
protection regions.</p></li>
</ul>
</section>
<section id="size-expansion">
<h2>Size Expansion<a class="headerlink" href="#size-expansion" title="Permalink to this heading"></a></h2>
<p>The protected build will, or course, result in a FLASH image that is
larger than that of the corresponding “flat” build. How much larger?
I don’t have the numbers in hand, but you can build
<code class="docutils literal notranslate"><span class="pre">boards/arm/stm32/stm32f4discovery/configs/nsh</span></code> and
<code class="docutils literal notranslate"><span class="pre">boards/arm/stm32/stm32f4discovery/configs/kostest</span></code> and compare
the resulting binaries for yourself using the <code class="docutils literal notranslate"><span class="pre">size</span></code> command.</p>
<p>Increases in size are expected because:</p>
<ul class="simple">
<li><p>The syscall layer is included in the protected build but not the flat
build.</p></li>
<li><p>The kernel-size _syscal_l stubs will cause all enabled OS code to be
drawn into the build. In the flat build, only those OS interfaces
actually called by the application will be included in the final objects.</p></li>
<li><p>The dual memory allocators will increase size.</p></li>
<li><p>Code duplication. Some code, such as the C library, will be
duplicated in both the kernel- and user-blobs, and</p></li>
<li><p>Alignment. The alignments required by the MPU logic will leave
relatively large regions of FLASH (and perhaps RAM) is not usable.</p></li>
</ul>
</section>
<section id="performance-issues">
<h2>Performance Issues<a class="headerlink" href="#performance-issues" title="Permalink to this heading"></a></h2>
<p>The only performance differences using the protected build should
result as a consequence of the <cite>sycalls</cite> used to interact with the
OS vs. the direct C calls as used in the flat build. If your
performance is highly dependent upon high rate OS calls, then
this could be an issue for you. But, in the typical application,
OS calls do not often figure into the critical performance paths.</p>
<p>The <cite>syscalls</cite> are, ultimately, software interrupts. If the platform
does not support prioritized, nested interrupts then the <cite>syscall</cite>
execution could also delay other hardware interrupt processing.
However, <cite>sycall</cite> processing is negligible: they really just
configure to return to in supervisor mode and vector to the
<cite>syscall</cite> stub. They should be lightning fast and, for the typical
real-time applications, should cause no issues.</p>
</section>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="integrate_newlib.html" class="btn btn-neutral float-left" title="Integrating with Newlib" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="platform_directories.html" class="btn btn-neutral float-right" title="Platform Directories" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2023, The Apache Software Foundation.</p>
</div>
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>