summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal@nekernel.org>2025-05-23 15:57:42 +0200
committerAmlal El Mahrouss <amlal@nekernel.org>2025-05-23 16:00:35 +0200
commite2bd3c7b6fcd6147fcbf699be087a475608ffdf7 (patch)
tree962ce7dd6efeda9dc6b96b9d0e47dfcc241f1c11
parent80f5f9dfdaaf68d9e63a7bc3ba1187ca447eadc9 (diff)
feat(krnl, libSystem, boot): Make space for LibSystem inside Handover
boot structure. what: - Mostly related to the libSystem.sys library. - Updated the implementation of it, the specs, and added new APIs. - Fixed the hooks inside AsmProc.h Signed-off-by: Amlal El Mahrouss <amlal@nekernel.org>
-rw-r--r--compile_flags.txt2
-rw-r--r--dev/boot/amd64-ci.make2
-rw-r--r--dev/boot/amd64-desktop.make2
-rw-r--r--dev/boot/src/HEL/AMD64/BootEFI.cc1
-rw-r--r--dev/generic_kits/BenchKit/Chrono.h15
-rw-r--r--dev/generic_kits/BenchKit/HardwareChrono.h9
-rw-r--r--dev/kernel/FirmwareKit/Handover.h6
-rw-r--r--dev/system_sdk/.keep (renamed from dev/generic_kits/BenchKit/.keep)0
-rw-r--r--dev/user/AsmProc.h (renamed from dev/user/SciCalls.h)0
-rw-r--r--dev/user/SecurityPolicy.h12
-rw-r--r--dev/user/SystemCalls.h33
-rw-r--r--dev/user/SystemCodes.h (renamed from dev/user/ProcessCodes.h)0
-rw-r--r--dev/user/docs/SPECIFICATION_SYSCALLS.md23
-rw-r--r--dev/user/src/GNUmakefile4
-rw-r--r--dev/user/src/SystemCalls+IO.asm21
-rw-r--r--dev/user/src/SystemCalls.cc6
-rw-r--r--dev/user/user.json4
-rw-r--r--docs/drawio/OS_DESIGN.drawio25
18 files changed, 119 insertions, 46 deletions
diff --git a/compile_flags.txt b/compile_flags.txt
index e9a887a3..6dd6300a 100644
--- a/compile_flags.txt
+++ b/compile_flags.txt
@@ -2,6 +2,8 @@
-Idev/
-Idev/user
-Idev/boot
+-Idev/system_sdk
+-Idev/generic_kits
-Idev/ddk
-Ipublic/tools
-Ipublic/tools/mk.app
diff --git a/dev/boot/amd64-ci.make b/dev/boot/amd64-ci.make
index b396b0d5..d711abde 100644
--- a/dev/boot/amd64-ci.make
+++ b/dev/boot/amd64-ci.make
@@ -73,7 +73,7 @@ BOOTLOADER=bootz.efi
KERNEL=krnl.efi
SYSCHK=chk.efi
BOOTNET=net.efi
-SCIKIT=user.sys
+SCIKIT=libSystem.sys
.PHONY: invalid-recipe
invalid-recipe:
diff --git a/dev/boot/amd64-desktop.make b/dev/boot/amd64-desktop.make
index 8c227ebf..05ac5db8 100644
--- a/dev/boot/amd64-desktop.make
+++ b/dev/boot/amd64-desktop.make
@@ -75,7 +75,7 @@ BOOTLOADER=bootz.efi
KERNEL=krnl.efi
SYSCHK=chk.efi
BOOTNET=net.efi
-SCIKIT=user.sys
+SCIKIT=libSystem.sys
DDK=ddk.sys
.PHONY: invalid-recipe
diff --git a/dev/boot/src/HEL/AMD64/BootEFI.cc b/dev/boot/src/HEL/AMD64/BootEFI.cc
index 84a4d295..58610c39 100644
--- a/dev/boot/src/HEL/AMD64/BootEFI.cc
+++ b/dev/boot/src/HEL/AMD64/BootEFI.cc
@@ -226,7 +226,6 @@ EFI_EXTERN_C EFI_API Int32 BootloaderMain(EfiHandlePtr image_handle, EfiSystemTa
// boot to kernel, if not bootnet this.
Boot::BootFileReader reader_kernel(kernel_path, image_handle);
-
reader_kernel.ReadAll(0);
// ------------------------------------------ //
diff --git a/dev/generic_kits/BenchKit/Chrono.h b/dev/generic_kits/BenchKit/Chrono.h
index b4010460..394f16fd 100644
--- a/dev/generic_kits/BenchKit/Chrono.h
+++ b/dev/generic_kits/BenchKit/Chrono.h
@@ -7,10 +7,25 @@ Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
#ifndef BENCHKIT_CHRONO_H
#define BENCHKIT_CHRONO_H
+#include <CompilerKit/CompilerKit.h>
#include <NeKit/Defines.h>
namespace Kernel {
class ChronoInterface;
+
+/// @brief a Chronometer interface used for benchmarking.
+class ChronoInterface {
+ public:
+ ChronoInterface() = default;
+ virtual ~ChronoInterface() = default;
+
+ NE_COPY_DEFAULT(ChronoInterface);
+
+ virtual void Start() = 0;
+ virtual void Stop() = 0;
+ virtual void Reset() = 0;
+ virtual UInt64 GetElapsedTime() const = 0;
+};
} // namespace Kernel
#endif // BENCHKIT_CHRONO_H
diff --git a/dev/generic_kits/BenchKit/HardwareChrono.h b/dev/generic_kits/BenchKit/HardwareChrono.h
new file mode 100644
index 00000000..f6f6fd8c
--- /dev/null
+++ b/dev/generic_kits/BenchKit/HardwareChrono.h
@@ -0,0 +1,9 @@
+/* -------------------------------------------
+
+Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#pragma once
+
+#include <BenchKit/Chrono.h>
diff --git a/dev/kernel/FirmwareKit/Handover.h b/dev/kernel/FirmwareKit/Handover.h
index 7689f38c..266953d3 100644
--- a/dev/kernel/FirmwareKit/Handover.h
+++ b/dev/kernel/FirmwareKit/Handover.h
@@ -61,8 +61,10 @@ struct BootInfoHeader final {
VoidPtr f_KernelImage;
SizeT f_KernelSz;
- VoidPtr f_StartupImage;
- SizeT f_StartupSz;
+
+ VoidPtr f_LibSystemImage;
+ SizeT f_LibSystemSz;
+
VoidPtr f_StackTop;
SizeT f_StackSz;
diff --git a/dev/generic_kits/BenchKit/.keep b/dev/system_sdk/.keep
index e69de29b..e69de29b 100644
--- a/dev/generic_kits/BenchKit/.keep
+++ b/dev/system_sdk/.keep
diff --git a/dev/user/SciCalls.h b/dev/user/AsmProc.h
index 4b3b63c1..4b3b63c1 100644
--- a/dev/user/SciCalls.h
+++ b/dev/user/AsmProc.h
diff --git a/dev/user/SecurityPolicy.h b/dev/user/SecurityPolicy.h
new file mode 100644
index 00000000..a03c928b
--- /dev/null
+++ b/dev/user/SecurityPolicy.h
@@ -0,0 +1,12 @@
+/* -------------------------------------------
+
+ Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#pragma once
+
+#include <user/SystemCalls.h>
+
+/// @file SecurityPolicy.h
+/// @brief Hardened Security Policy, used to restrict access to certain system calls. \ No newline at end of file
diff --git a/dev/user/SystemCalls.h b/dev/user/SystemCalls.h
index 61021a01..c1b70513 100644
--- a/dev/user/SystemCalls.h
+++ b/dev/user/SystemCalls.h
@@ -112,7 +112,7 @@ IMPORT_C UInt64 IoSeekFile(_Input Ref file_desc, UInt64 file_offset);
/// @brief Spawns a Thread Information Block and Global Information Block inside the current
/// process.
/// @param process_id Target Process ID, must be valid.
-/// @return > 0 error ocurred or already present, = 0 success.
+/// @return > 0 error occurred or already present, = 0 success.
IMPORT_C UInt32 RtlSpawnIB(UIntPtr process_id);
/// @brief Spawns a process with a unique pid (stored as UIntPtr).
@@ -125,10 +125,6 @@ IMPORT_C UIntPtr RtlSpawnProcess(const Char* process_path, SizeT argc, Char** ar
/// @return if it has succeeded true, otherwise false.
IMPORT_C Bool RtlExitProcess(UIntPtr handle, UIntPtr exit_code);
-/// @brief Get current PID of process.
-/// @return Current process ID.
-IMPORT_C UIntPtr RtlCurrentPID(Void);
-
// ------------------------------------------------------------------------
// Memory Manager API.
// ------------------------------------------------------------------------
@@ -192,14 +188,15 @@ IMPORT_C SInt32 ThrExitMainThread(_Input SInt32 exit_code);
IMPORT_C SInt32 ThrExitThread(_Input ThreadRef thread, _Input SInt32 exit_code);
/// @brief Thread procedure function type.
-typedef SInt32 (*thread_proc_kind)(SInt32 argc, Char** argv);
+typedef SInt32 (*ThrProcKind)(SInt32 argc, Char** argv);
/// @brief Creates a thread.
/// @param procedure the thread procedure.
/// @param argument_count number of arguments inside that thread.
/// @param flags Thread flags.
/// @return the thread object.
-IMPORT_C ThreadRef ThrCreateThread(thread_proc_kind procedure, SInt32 argument_count, SInt32 flags);
+IMPORT_C ThreadRef ThrCreateThread(const Char* thread_name, ThrProcKind procedure,
+ SInt32 argument_count, SInt32 flags);
/// @brief Yields the current thread.
/// @param thread the thread to yield.
@@ -287,8 +284,8 @@ IMPORT_C VoidPtr EvtDispatchEvent(_Input const Char* event_name, _Input VoidPtr
// ------------------------------------------------------------------------------------------ //
enum {
- kPowerCodeInvalid,
- kPowerCodeShutdown,
+ kPowerCodeInvalid = 0,
+ kPowerCodeShutdown = 12,
kPowerCodeReboot,
kPowerCodeSleep,
kPowerCodeWake,
@@ -328,15 +325,21 @@ IMPORT_C IORef PrintGet(const Char* path);
// ------------------------------------------------------------------------------------------ //
typedef SInt32 AffinityRef;
-typedef UInt64 PID;
+typedef UInt64 ProcessRef;
+
+IMPORT_C SInt32 SchedSetAffinity(ProcessRef, SInt32 req, AffinityRef* local);
-IMPORT_C SInt32 SchedAffinity(PID, SInt32 req, AffinityRef* local);
+IMPORT_C SInt32 SchedGetAffinity(ProcessRef, AffinityRef* local);
-IMPORT_C SInt32 SchedTrace(PID, SInt32 req, VoidPtr address, VoidPtr data);
+IMPORT_C SInt32 SchedFireSignal(ProcessRef, SInt32 req);
-IMPORT_C SInt32 SchedKill(PID, SInt32 req);
+IMPORT_C SInt32 SchedReadMemory(ProcessRef, SInt32 address, SInt32 data);
-IMPORT_C SInt32 SchedBreakPoint(Void);
+IMPORT_C SInt32 SchedWriteMemory(ProcessRef, SInt32 address, SInt32 data);
+
+/// @brief Get current ProcessRef of process.
+/// @return Current process ID.
+IMPORT_C UIntPtr RtlCurrentPID(Void);
// ------------------------------------------------------------------------------------------ //
// @brief Filesystem API.
@@ -355,7 +358,7 @@ IMPORT_C BOOL FsCreateFile(const Char* path);
IMPORT_C BOOL FsCreateAlias(const Char* path, const Char* from);
// ------------------------------------------------------------------------------------------ //
-// @brief Format API.
+// @brief String API.
// ------------------------------------------------------------------------------------------ //
IMPORT_C Char* StrFmt(const Char* fmt, ...);
diff --git a/dev/user/ProcessCodes.h b/dev/user/SystemCodes.h
index 90457944..90457944 100644
--- a/dev/user/ProcessCodes.h
+++ b/dev/user/SystemCodes.h
diff --git a/dev/user/docs/SPECIFICATION_SYSCALLS.md b/dev/user/docs/SPECIFICATION_SYSCALLS.md
index 607c7532..b4b11c8c 100644
--- a/dev/user/docs/SPECIFICATION_SYSCALLS.md
+++ b/dev/user/docs/SPECIFICATION_SYSCALLS.md
@@ -1,16 +1,25 @@
===================================
-
# 0: General Information
-
===================================
-- Programming Language: C/C++
-- Build System: Make/BTB
-- Purpose: System Call Interface
+- **Programming Language**: C / C++
+- **Build System**: Make / BTB (Build the Build)
+- **Purpose**: System Call Interface (SCI) for NeKernel
===================================
+# 1: How It Works
+===================================
-# 1: How It works
+- This header provides the raw API surface for accessing NeKernel's system calls.
-===================================
+- It is **not** directly used by applications.
+ - Instead, it is abstracted by the **SystemSDK**, which presents a stable, high-level interface.
+
+- At runtime:
+ - System calls are routed from user-space code to the **kernel syscall manager**.
+ - The syscall manager executes the requested operation and returns control to `libSystem`.
+ - Finally, the result is delivered back to the originating process.
+- This separation ensures that:
+ - The SCI remains low-level and close to the ABI.
+ - `SystemSDK` provides portability and shielding from changes in syscall internals. \ No newline at end of file
diff --git a/dev/user/src/GNUmakefile b/dev/user/src/GNUmakefile
index 09993d16..9b901f9f 100644
--- a/dev/user/src/GNUmakefile
+++ b/dev/user/src/GNUmakefile
@@ -1,6 +1,6 @@
##################################################
# (c) Amlal El Mahrouss, all rights reserved.
-# This file is for user.sys's syscall stubs.
+# This file is for libSystem.sys's syscall stubs.
##################################################
ASM=nasm
@@ -13,4 +13,4 @@ error:
.PHONY: sci_asm_io_x64
sci_asm_io_x64:
- $(ASM) $(FLAGS) SystemCalls+IO.asm -o SystemCalls+IO.asm.o
+ $(ASM) $(FLAGS) SystemCalls+IO.asm -o SystemCalls+IO.stub.obj
diff --git a/dev/user/src/SystemCalls+IO.asm b/dev/user/src/SystemCalls+IO.asm
index 77e22b59..9126b7de 100644
--- a/dev/user/src/SystemCalls+IO.asm
+++ b/dev/user/src/SystemCalls+IO.asm
@@ -19,17 +19,31 @@ global sci_syscall_arg_3
global sci_syscall_arg_4
sci_syscall_arg_1:
+ push rbp
+ mov rbp, rsp
+
mov r8, rcx
syscall
+
+ pop rbp
+
ret
sci_syscall_arg_2:
+ push rbp
+ mov rbp, rsp
+
mov r8, rcx
mov r9, rdx
syscall
+ pop rbp
+
ret
sci_syscall_arg_3:
+ push rbp
+ mov rbp, rsp
+
mov rbx, r8
mov r8, rcx
@@ -37,9 +51,14 @@ sci_syscall_arg_3:
mov r10, rbx
syscall
+ pop rbp
+
ret
sci_syscall_arg_4:
+ push rbp
+ mov rbp, rsp
+
mov rbx, r8
mov rax, r9
@@ -49,4 +68,6 @@ sci_syscall_arg_4:
mov r11, rax
syscall
+ pop rbp
+
ret
diff --git a/dev/user/src/SystemCalls.cc b/dev/user/src/SystemCalls.cc
index 874f607d..f004718c 100644
--- a/dev/user/src/SystemCalls.cc
+++ b/dev/user/src/SystemCalls.cc
@@ -4,11 +4,11 @@
------------------------------------------- */
-#include <user/SciCalls.h>
+#include <user/AsmProc.h>
#include <user/SystemCalls.h>
/// @file SystemCalls.cc
-/// @brief Source file for the memory functions/syscalls for user.sys
+/// @brief Source file for the memory functions/syscalls for libSystem.sys
IMPORT_C VoidPtr MmCopyMemory(_Input VoidPtr dest, _Input VoidPtr src, _Input SizeT len) {
if (!len || !dest || !src) {
@@ -51,8 +51,6 @@ IMPORT_C VoidPtr MmFillMemory(_Input VoidPtr dest, _Input SizeT len, _Input UInt
/// @internal
//-----------------------------------------------------------------------------------------------------------//
-constexpr auto kInvalidSyscall = 0UL;
-
IMPORT_C Ref IoOpenFile(_Input const Char* path, _Input const Char* drv_letter) {
return sci_syscall_arg_3(1, reinterpret_cast<VoidPtr>(const_cast<Char*>(path)),
reinterpret_cast<VoidPtr>(const_cast<Char*>(drv_letter)));
diff --git a/dev/user/user.json b/dev/user/user.json
index 05b90abf..2267175e 100644
--- a/dev/user/user.json
+++ b/dev/user/user.json
@@ -2,8 +2,8 @@
"compiler_path": "x86_64-w64-mingw32-g++",
"compiler_std": "c++20",
"headers_path": ["../", "./"],
- "sources_path": ["src/*.cc", "src/*.o"],
- "output_name": "user.sys",
+ "sources_path": ["src/*.cc", "src/*.stub.obj"],
+ "output_name": "libSystem.sys",
"compiler_flags": [
"-ffreestanding",
"-shared",
diff --git a/docs/drawio/OS_DESIGN.drawio b/docs/drawio/OS_DESIGN.drawio
index c9276302..3a03540c 100644
--- a/docs/drawio/OS_DESIGN.drawio
+++ b/docs/drawio/OS_DESIGN.drawio
@@ -1,14 +1,14 @@
<mxfile host="65bd71144e">
<diagram name="Page-1" id="lDkK2i6CeL2VbSOVDvrP">
- <mxGraphModel dx="1142" dy="713" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
+ <mxGraphModel dx="960" dy="709" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
- <mxCell id="ifhO3zQZNW-sXvZMTmu8-2" value="&lt;p class=&quot;p1&quot;&gt;&lt;b&gt;System API (user.sys&lt;/b&gt;&lt;b style=&quot;background-color: transparent;&quot;&gt;) – User-Space Interface (Ring 3, EL0)&lt;/b&gt;&lt;/p&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
+ <mxCell id="ifhO3zQZNW-sXvZMTmu8-2" value="&lt;p class=&quot;p1&quot;&gt;&lt;b&gt;System API (libSystem.sys&lt;/b&gt;&lt;b style=&quot;background-color: transparent;&quot;&gt;) – User-Space Interface (Ring 3, EL0)&lt;/b&gt;&lt;/p&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="240" y="340" width="360" height="30" as="geometry"/>
</mxCell>
<mxCell id="ifhO3zQZNW-sXvZMTmu8-3" value="&lt;p class=&quot;p1&quot;&gt;&lt;b&gt;Applications &amp;amp; Dynamically Linked Libraries (Ring 3, EL0)&lt;/b&gt;&lt;/p&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
- <mxGeometry x="240" y="295" width="360" height="35" as="geometry"/>
+ <mxGeometry x="240" y="240" width="360" height="35" as="geometry"/>
</mxCell>
<mxCell id="ifhO3zQZNW-sXvZMTmu8-13" value="&lt;p class=&quot;p1&quot;&gt;&lt;b&gt;NeKernel MP Kernel, DDK, and Drivers (Ring 0, EL1)&lt;/b&gt;&lt;/p&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="240" y="450" width="360" height="60" as="geometry"/>
@@ -16,27 +16,30 @@
<mxCell id="4" value="&lt;p class=&quot;p1&quot;&gt;&lt;b&gt;SCI and DDK Kernel Calls (Ring 0 / Ring 2, EL0 to EL1 Transitions)&lt;/b&gt;&lt;/p&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="240" y="380" width="360" height="60" as="geometry"/>
</mxCell>
- <mxCell id="5" value="&lt;p class=&quot;p1&quot;&gt;&lt;b&gt;HAL&lt;/b&gt;&lt;/p&gt;" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxCell id="5" value="&lt;p class=&quot;p1&quot;&gt;&lt;b&gt;HAL&lt;/b&gt;&lt;/p&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="404.5" y="525" width="195.5" height="60" as="geometry"/>
</mxCell>
- <mxCell id="6" value="&lt;p class=&quot;p1&quot;&gt;&lt;b&gt;Kernel Kits&lt;/b&gt;&lt;/p&gt;" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxCell id="6" value="&lt;p class=&quot;p1&quot;&gt;&lt;b&gt;Kernel Kits&lt;/b&gt;&lt;/p&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="240" y="525" width="154.5" height="60" as="geometry"/>
</mxCell>
- <mxCell id="7" value="&lt;p class=&quot;p1&quot;&gt;&lt;b&gt;BootZ Bootloader and Handover&lt;/b&gt;&lt;/p&gt;" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxCell id="7" value="&lt;p class=&quot;p1&quot;&gt;&lt;b&gt;BootZ Bootloader and Handover&lt;/b&gt;&lt;/p&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="240" y="600" width="360" height="60" as="geometry"/>
</mxCell>
- <mxCell id="9" value="&lt;p class=&quot;p1&quot;&gt;&lt;b&gt;Firmware (EFI, NeKernel.org&#39;s FW)&lt;/b&gt;&lt;/p&gt;" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxCell id="9" value="&lt;p class=&quot;p1&quot;&gt;&lt;b&gt;Firmware (EFI, NeKernel.org&#39;s FW)&lt;/b&gt;&lt;/p&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="240" y="670" width="357.75" height="60" as="geometry"/>
</mxCell>
- <mxCell id="10" value="Privileged" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
+ <mxCell id="10" value="Privileged" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="660" y="460" width="60" height="30" as="geometry"/>
</mxCell>
- <mxCell id="11" value="User" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
- <mxGeometry x="660" y="295" width="60" height="30" as="geometry"/>
+ <mxCell id="11" value="User" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
+ <mxGeometry x="660" y="300" width="60" height="30" as="geometry"/>
</mxCell>
- <mxCell id="12" value="Driver" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
+ <mxCell id="12" value="Driver" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="660" y="380" width="60" height="30" as="geometry"/>
</mxCell>
+ <mxCell id="13" value="&lt;p class=&quot;p1&quot;&gt;&lt;b&gt;System SDK Stable API&lt;/b&gt;&lt;/p&gt;" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+ <mxGeometry x="238.88" y="290" width="360" height="40" as="geometry"/>
+ </mxCell>
</root>
</mxGraphModel>
</diagram>