refactor: decouple the gcc version requirement.
refactor: add implementation to arch-aware division, this allows removal of libgcc
fix: couple bugs in builtin user shell
updated readme
<a href="#lunaixos-project">简体中文</a> | <a href="docs/README_en.md">English</a>
</p>
-# LunaixOS Project
+# The LunaixOS Project
LunaixOS - 一个简单的,详细的,POSIX兼容的(但愿!),带有浓重个人风格的操作系统。开发过程以视频教程形式在Bilibili呈现:[《从零开始自制操作系统系列》](https://space.bilibili.com/12995787/channel/collectiondetail?sid=196337)。
-## 一些实用资源
+## 1. 一些实用资源
如果有意研读LunaixOS的内核代码和其中的设计,以下资料可能会对此有用。
+ [LunaixOS启动流程概览](docs/img/boot_sequence.jpeg)
+ LunaixOS总体架构概览(WIP)
-## 当前进度以及支持的功能
+## 2. 当前进度以及支持的功能
该操作系统支持x86架构,运行在保护模式中,采用宏内核架构,目前仅支持单核心。架构与内核的解耦合工作正在进行中。
+ APIC/IOAPIC作为中断管理器和计时器
+ ACPI
+ 虚拟内存
-+ 内存管理与按需分页(Demand Paging)
++ 内存管理与按需分页
+ 键盘输入
+ 多进程
+ 54个常见的Linux/POSIX系统调用([附录1](#appendix1))
+ 通用设备抽象层
+ 通用图形设备抽象层
+ 标准VGA实现
++ 虚拟终端设备接口(兼容 POSIX.1-2008)
已经测试过的环境:
+ Virtualbox
+ Dell G3 3779
-## 目录结构
+## 3. 目录结构
| | |
| ----------------------------------------- | ---------------------------- |
| [slides](slides/) | 视频中所用的幻灯片和补充材料 |
| [reference-material](reference-material/) | 标准,技术文档和参考文献 |
-## 编译与构建
-
-### 环境搭建
+## 4. 编译与构建
构建该项目需要满足以下条件:
-+ gcc (目标平台: i686-elf)
-+ binutils
++ gcc 工具链
+ make
+ xorriso
+ grub-mkrescue
-**注意:gcc不能是本机自带的,必须要从源码编译,并配置目标平台为:`i686-elf`,以进行交叉编译。配置过程可参考[附录二:编译gcc作为交叉编译器](#appendix2)。**
+### 4.1 使用 GNU CC 工具链
+
+正如同大多数OS一样,LunaixOS 是一个混合了 C 和汇编的产物。这就意味着你得要使用一些标准的C编译器来构建Lunaix。在这里,我推荐使用 GNU CC 工具链来进行构建。至于其他的工具链,如llvm,也可以去尝试,但对此我就不能作任何的保证了。
+
+如果你使用的是基于 x86 指令集的Linux系统,不论是64位还是32位,**其本机自带的gcc就足以编译Lunaix**。 当然了,如果说你的平台是其他非x86的,你也可以指定使用某个针对x86_32的gcc套件来进行交叉编译——在`make`时通过`CX_PREFIX`变量来指定gcc套件的前缀。如下例所示,我们可以在任意平台上,如risc-v,单独使用一个面向x86_32的gcc来进行交叉编译:
+
+```
+make CX_PREFIX=i686-linux-gnu- all
+```
+
+由于目前Lunaix仅支持x86_32微架构, `CX_PREFIX` 指向的gcc必须具有针对x86_32架构进行交叉编译的能力。
-### Docker镜像
+### 4.2 Docker镜像
对于开发环境,本项目也提供了Docker镜像封装。开箱即用,无需配置,非常适合懒人或惜时者。详细使用方法请转到:[Lunaix OSDK项目](https://github.com/Minep/os-devkit)。
-### 构建选项
+### 4.3 构建选项
假若条件满足,那么可以直接执行`make all`进行构建,完成后可在生成的`build`目录下找到可引导的iso。
**※:由于在`-O2`模式下,GCC会进行CSE优化,这导致LunaixOS会出现一些非常奇怪、离谱的bug,从而影响到基本运行。具体原因有待调查。**
-## 运行,分支以及 Issue
+## 5. 运行,分支以及 Issue
+
+### 5.1 虚拟磁盘(非必须)
-运行该操作系统需要一个虚拟磁盘镜像,可以使用如下命令快速创建一个:
+你可以绑定一个虚拟磁盘镜像,可以使用如下命令快速创建一个:
```bash
qemu-img create -f vdi machine/disk0.vdi 128M
有很多办法去创建一个虚拟磁盘,比如[qemu-img](https://qemu-project.gitlab.io/qemu/system/images.html)。
+### 5.2 代码稳定性
+
主分支一般是稳定的。因为在大多数情况下,我都会尽量保证本机运行无误后,push到该分支中。至于其他的分支,则是作为标记或者是开发中的功能。前者标记用分支一般会很快删掉;后者开发分支不能保证稳定性,这些分支的代码有可能没有经过测试,但可以作为Lunaix当前开发进度的参考。
该系统是经过虚拟机和真机测试。如果发现在使用`make all`之后,虚拟机中运行报错,则一般是编译器优化问题。这个问题笔者一般很快就会修复,如果你使用别的版本的gcc(笔者版本11.2),出现了此问题,欢迎提issue。请参考[附录3:Issue的提交](#appendix3)
正常,**因为Bochs不支持SATA**。请使用QEMU或VirtualBox。
-## 调试 Lunaix 内核
+## 6. 调试 Lunaix 内核
除了[附录4:串口GDB远程调试](#appendix4)描述的一种用于实机调试的方式以外。LunaixOS还提供了LunaDBG调试套件。这是一个GDB客户端插件,包含了对GDB原生命令集的一些扩充,主要用于改善与简化内核调试的过程。目前包含以下几个命令:
./scripts/gdb/install_lunadbg
```
-## 参考教程
+## 7. 参考教程
**没有!!** 本教程以及该操作系统均为原创,没有基于任何市面上现行的操作系统开发教程,且并非是基于任何的开源内核的二次开发。
( **※**:该系统调用暂未经过测试 )
-## 附录2:编译gcc作为交叉编译器<a id="appendix2"></a>
+## 附录2:Issue的提交<a id="appendix3"></a>
-注意,gcc需要从源码构建,并配置为交叉编译器,即目标平台为`i686-elf`。你可以使用本项目提供的[自动化脚本](slides/c0-workspace/gcc-build.sh),这将会涵盖gcc和binutils源码的下载,配置和编译(没什么时间去打磨脚本,目前只知道在笔者的Ubuntu系统上可以运行)。
-
-**推荐**手动编译。以下编译步骤搬运自:<https://wiki.osdev.org/GCC_Cross-Compiler>
-
-**首先安装构建依赖项:**
-
-```bash
-sudo apt update &&\
- apt install -y \
- build-essential \
- bison\
- flex\
- libgmp3-dev\
- libmpc-dev\
- libmpfr-dev\
- texinfo
-```
-
-**开始编译:**
-
-1. 获取[gcc](https://ftp.gnu.org/gnu/gcc/)和[binutils](https://ftp.gnu.org/gnu/binutils)源码
-2. 解压,并在同级目录为gcc和binutil新建专门的build文件夹
-
-现在假设你的目录结构如下:
-
-```
-+ folder
- + gcc-src
- + binutils-src
- + gcc-build
- + binutils-build
-```
-
-3. 确定gcc和binutil安装的位置,并设置环境变量:`export PREFIX=<安装路径>` 然后设置PATH: `export PATH="$PREFIX/bin:$PATH"`
-4. 设置目标平台:`export TARGET=i686-elf`
-5. 进入`binutils-build`进行配置
-
-```bash
-../binutils-src/configure --target="$TARGET" --prefix="$PREFIX" \
- --with-sysroot --disable-nls --disable-werror
-```
-
-然后 `make && make install`
-
-6. 确保上述的`binutils`已经正常安装:执行:`which i686-elf-as`,应该会给出一个位于你安装目录下的路径。
-6. 进入`gcc-build`进行配置
-
-```bash
-../gcc-src/configure --target="$TARGET" --prefix="$PREFIX" \
- --disable-nls --enable-languages=c,c++ --without-headers
-```
-
-然后编译安装(取决性能,大约10~20分钟):
-
-```bash
-make all-gcc &&\
- make all-target-libgcc &&\
- make install-gcc &&\
- make install-target-libgcc
-```
-
-8. 验证安装:执行`i686-elf-gcc -dumpmachine`,输出应该为:`i686-elf`
-
-**将新编译好的GCC永久添加到`PATH`环境变量**
-
-虽然这是一个常识性的操作,但考虑到许多人都会忽略这一个额外的步骤,在这里特此做出提示。
-
-要想实现这一点,只需要在shell的配置文件的末尾添加:`export PATH="<上述的安装路径>/bin:$PATH"`。
-
-这个配置文件是取决于你使用的shell,如zsh就是`${HOME}/.zshrc`,bash则是`${HOME}/.bashrc`;或者你嫌麻烦的,懒得区分,你也可以直接修改全局的`/etc/profile`文件,一劳永逸(但不推荐这样做)。
-
-至于其他的情况,由于这个步骤其实在网上是随处可查的,所以就不在这里赘述了。
-
-## 附录3:Issue的提交<a id="appendix3"></a>
-
-由于目前LunaixOS没有一个完善强大的内核追踪功能。假若Lunaix的运行出现任何问题,还请按照以下的描述,在Issue里面提供详细的信息。
-
-最好提供:
+假若Lunaix的运行出现任何问题,还请按照以下的描述,在Issue里面提供详细的信息。
+ 可用于复现问题的描述和指引(如Lunaix运行平台的软硬件配置)
+ 错误症状描述
-+ (如可能)运行截图
-+ 错误消息(如果给出)
-+ 寄存器状态的dump
-+ (如可能)提供错误发生时,EIP附近的指令(精确到函数)。如果使用`make all-debug`,会提供`build/kdump.txt`,你可以在这里面定位。或者也可以直接`objdump`
-+ (如可能)虚拟内存映射信息(QEMU下可使用`info mem`查看)。
++ LunaixOS在panic时打印的调试信息(如无法复制,可以截图)
+
+## 附录3:串口GDB远程调试<a id="appendix4"></a>
-## 附录4:串口GDB远程调试<a id="appendix4"></a>
+**(该功能正在重构,目前不可用)**
LunaixOS内核集成了最基本的GDB远程调试服务器。可通过串口COM1在9600波特率上与之建立链接。但是,在将GDB与内核链接起来之前,还需要让内核处在调试模式下。
在目前,为了防止代码过于臃肿,LunaixOS实现的是GDB远程协议要求的最小服务端命令子集:`g`, `G`, `p`, `P`, `Q`, `S`, `k`, `?`, `m`, `M`, `X`。足以满足大部分的调试需求。
当结束调试的时候,请使用GDB的`kill`指令进行连接的断开。注意,这个指令会使得LunaixOS恢复所有暂停的活动,进入正常的运行序列,但并不会退出调试模式。GDB的挂载请求依然在LunaixOS中享有最高优先权。如果需要退出调试模式,需要往串口写入字节串:`0x40` `0x79` `0x61` `0x79`。
-
-### GDB调试注意事项
-
-在调试中,请避免使用`info stack`,`bt`或者任何涉及 **栈展开(Stack Unwinding)** 或者 **栈回溯(Stack Backtracing)** 的指令。否则,LunaixOS很有可能会出现 **不可预料的行为** 。
--- /dev/null
+# 编译gcc作为交叉编译器<a id="appendix2"></a>
+
+注意,gcc需要从源码构建,并配置为交叉编译器,即目标平台为`i686-elf`。你可以使用本项目提供的[自动化脚本](slides/c0-workspace/gcc-build.sh),这将会涵盖gcc和binutils源码的下载,配置和编译(没什么时间去打磨脚本,目前只知道在笔者的Ubuntu系统上可以运行)。
+
+**推荐**手动编译。以下编译步骤搬运自:<https://wiki.osdev.org/GCC_Cross-Compiler>
+
+**首先安装构建依赖项:**
+
+```bash
+sudo apt update &&\
+ apt install -y \
+ build-essential \
+ bison\
+ flex\
+ libgmp3-dev\
+ libmpc-dev\
+ libmpfr-dev\
+ texinfo
+```
+
+**开始编译:**
+
+1. 获取[gcc](https://ftp.gnu.org/gnu/gcc/)和[binutils](https://ftp.gnu.org/gnu/binutils)源码
+2. 解压,并在同级目录为gcc和binutil新建专门的build文件夹
+
+现在假设你的目录结构如下:
+
+```
++ folder
+ + gcc-src
+ + binutils-src
+ + gcc-build
+ + binutils-build
+```
+
+3. 确定gcc和binutil安装的位置,并设置环境变量:`export PREFIX=<安装路径>` 然后设置PATH: `export PATH="$PREFIX/bin:$PATH"`
+4. 设置目标平台:`export TARGET=i686-elf`
+5. 进入`binutils-build`进行配置
+
+```bash
+../binutils-src/configure --target="$TARGET" --prefix="$PREFIX" \
+ --with-sysroot --disable-nls --disable-werror
+```
+
+然后 `make && make install`
+
+6. 确保上述的`binutils`已经正常安装:执行:`which i686-elf-as`,应该会给出一个位于你安装目录下的路径。
+6. 进入`gcc-build`进行配置
+
+```bash
+../gcc-src/configure --target="$TARGET" --prefix="$PREFIX" \
+ --disable-nls --enable-languages=c,c++ --without-headers
+```
+
+然后编译安装(取决性能,大约10~20分钟):
+
+```bash
+make all-gcc &&\
+ make all-target-libgcc &&\
+ make install-gcc &&\
+ make install-target-libgcc
+```
+
+8. 验证安装:执行`i686-elf-gcc -dumpmachine`,输出应该为:`i686-elf`
+
+**将新编译好的GCC永久添加到`PATH`环境变量**
+
+虽然这是一个常识性的操作,但考虑到许多人都会忽略这一个额外的步骤,在这里特此做出提示。
+
+要想实现这一点,只需要在shell的配置文件的末尾添加:`export PATH="<上述的安装路径>/bin:$PATH"`。
+
+这个配置文件是取决于你使用的shell,如zsh就是`${HOME}/.zshrc`,bash则是`${HOME}/.bashrc`;或者你嫌麻烦的,懒得区分,你也可以直接修改全局的`/etc/profile`文件,一劳永逸(但不推荐这样做)。
+
+至于其他的情况,由于这个步骤其实在网上是随处可查的,所以就不在这里赘述了。
-# ---
-# Language: Cpp
-# # BasedOnStyle: Mozilla
-# AccessModifierOffset: -2
-# AlignAfterOpenBracket: Align
-AlignConsecutiveMacros: false
-AlignConsecutiveAssignments: false
-AlignConsecutiveDeclarations: false
-AlignEscapedNewlines: Right
-AlignOperands: true
-AlignTrailingComments: true
-# AllowAllArgumentsOnNextLine: true
-# AllowAllConstructorInitializersOnNextLine: true
-# AllowAllParametersOfDeclarationOnNextLine: false
-AllowShortBlocksOnASingleLine: Never
-# AllowShortCaseLabelsOnASingleLine: false
-AllowShortFunctionsOnASingleLine: Inline
-# AllowShortLambdasOnASingleLine: All
-# AllowShortIfStatementsOnASingleLine: Never
-# AllowShortLoopsOnASingleLine: false
-# AlwaysBreakAfterDefinitionReturnType: TopLevel
-AlwaysBreakAfterReturnType: TopLevel
-# AlwaysBreakBeforeMultilineStrings: false
-AlwaysBreakTemplateDeclarations: Yes
-BinPackArguments: false
-BinPackParameters: false
-BraceWrapping:
- AfterCaseLabel: false
- AfterClass: true
- AfterControlStatement: false
- AfterEnum: true
- AfterFunction: true
- AfterNamespace: false
- AfterObjCDeclaration: false
- AfterStruct: true
- AfterUnion: true
- AfterExternBlock: true
- BeforeCatch: false
- BeforeElse: false
- IndentBraces: false
- SplitEmptyFunction: true
- SplitEmptyRecord: false
- SplitEmptyNamespace: true
-# BreakBeforeBinaryOperators: None
-BreakBeforeBraces: Mozilla
-# BreakBeforeInheritanceComma: false
-# BreakInheritanceList: BeforeComma
-BreakBeforeTernaryOperators: true
-# BreakConstructorInitializersBeforeComma: false
-# BreakConstructorInitializers: BeforeComma
-# BreakAfterJavaFieldAnnotations: false
-BreakStringLiterals: true
-ColumnLimit: 80
-# CommentPragmas: "^ IWYU pragma:"
-# CompactNamespaces: false
-# ConstructorInitializerAllOnOneLineOrOnePerLine: false
-# ConstructorInitializerIndentWidth: 2
+# # ---
+# # Language: Cpp
+# # # BasedOnStyle: Mozilla
+# # AccessModifierOffset: -2
+# # AlignAfterOpenBracket: Align
+# AlignConsecutiveMacros: false
+# AlignConsecutiveAssignments: false
+# AlignConsecutiveDeclarations: false
+# AlignEscapedNewlines: Right
+# AlignOperands: true
+# AlignTrailingComments: true
+# # AllowAllArgumentsOnNextLine: true
+# # AllowAllConstructorInitializersOnNextLine: true
+# # AllowAllParametersOfDeclarationOnNextLine: false
+# AllowShortBlocksOnASingleLine: Never
+# # AllowShortCaseLabelsOnASingleLine: false
+# AllowShortFunctionsOnASingleLine: Inline
+# # AllowShortLambdasOnASingleLine: All
+# # AllowShortIfStatementsOnASingleLine: Never
+# # AllowShortLoopsOnASingleLine: false
+# # AlwaysBreakAfterDefinitionReturnType: TopLevel
+# AlwaysBreakAfterReturnType: TopLevel
+# # AlwaysBreakBeforeMultilineStrings: false
+# AlwaysBreakTemplateDeclarations: Yes
+# BinPackArguments: false
+# BinPackParameters: false
+# BraceWrapping:
+# AfterCaseLabel: false
+# AfterClass: true
+# AfterControlStatement: false
+# AfterEnum: true
+# AfterFunction: true
+# AfterNamespace: false
+# AfterObjCDeclaration: false
+# AfterStruct: true
+# AfterUnion: true
+# AfterExternBlock: true
+# BeforeCatch: false
+# BeforeElse: false
+# IndentBraces: false
+# SplitEmptyFunction: true
+# SplitEmptyRecord: false
+# SplitEmptyNamespace: true
+# # BreakBeforeBinaryOperators: None
+# BreakBeforeBraces: Mozilla
+# # BreakBeforeInheritanceComma: false
+# # BreakInheritanceList: BeforeComma
+# BreakBeforeTernaryOperators: true
+# # BreakConstructorInitializersBeforeComma: false
+# # BreakConstructorInitializers: BeforeComma
+# # BreakAfterJavaFieldAnnotations: false
+# BreakStringLiterals: true
+# ColumnLimit: 80
+# # CommentPragmas: "^ IWYU pragma:"
+# # CompactNamespaces: false
+# # ConstructorInitializerAllOnOneLineOrOnePerLine: false
+# # ConstructorInitializerIndentWidth: 2
# ContinuationIndentWidth: 2
-# Cpp11BracedListStyle: false
-# DeriveLineEnding: true
-# DerivePointerAlignment: false
-# DisableFormat: false
-# ExperimentalAutoDetectBinPacking: false
-# FixNamespaceComments: false
-ForEachMacros:
- - foreach
- - Q_FOREACH
- - BOOST_FOREACH
-# IncludeBlocks: Preserve
-# IncludeCategories:
-# - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
-# Priority: 2
-# SortPriority: 0
-# - Regex: '^(<|"(gtest|gmock|isl|json)/)'
-# Priority: 3
-# SortPriority: 0
-# - Regex: ".*"
-# Priority: 1
-# SortPriority: 0
-# IncludeIsMainRegex: "(Test)?$"
-# IncludeIsMainSourceRegex: ""
-IndentCaseLabels: true
-IndentGotoLabels: true
-IndentPPDirectives: None
-IndentWidth: 4
-# IndentWrappedFunctionNames: false
-# JavaScriptQuotes: Leave
-# JavaScriptWrapImports: true
-KeepEmptyLinesAtTheStartOfBlocks: true
-# MacroBlockBegin: ""
-# MacroBlockEnd: ""
-MaxEmptyLinesToKeep: 1
-# NamespaceIndentation: None
-# ObjCBinPackProtocolList: Auto
-# ObjCBlockIndentWidth: 2
-# ObjCSpaceAfterProperty: true
-# ObjCSpaceBeforeProtocolList: false
-# PenaltyBreakAssignment: 2
-# PenaltyBreakBeforeFirstCallParameter: 19
-# PenaltyBreakComment: 300
-# PenaltyBreakFirstLessLess: 120
-# PenaltyBreakString: 1000
-# PenaltyBreakTemplateDeclaration: 10
-# PenaltyExcessCharacter: 1000000
-# PenaltyReturnTypeOnItsOwnLine: 200
-PointerAlignment: Left
-# ReflowComments: true
-SortIncludes: true
-# SortUsingDeclarations: true
-SpaceAfterCStyleCast: false
-SpaceAfterLogicalNot: false
-SpaceAfterTemplateKeyword: false
-SpaceBeforeAssignmentOperators: true
-SpaceBeforeCpp11BracedList: false
-SpaceBeforeCtorInitializerColon: true
-SpaceBeforeInheritanceColon: true
-SpaceBeforeParens: ControlStatements
-SpaceBeforeRangeBasedForLoopColon: true
-SpaceInEmptyBlock: false
-SpaceInEmptyParentheses: false
-SpacesBeforeTrailingComments: 1
-SpacesInAngles: false
-SpacesInConditionalStatement: false
-SpacesInContainerLiterals: true
-SpacesInCStyleCastParentheses: false
-SpacesInParentheses: false
-SpacesInSquareBrackets: false
-SpaceBeforeSquareBrackets: false
-Standard: Latest
-StatementMacros:
- - Q_UNUSED
- - QT_REQUIRE_VERSION
-# TabWidth: 8
-UseCRLF: false
-UseTab: Never
-# ---
+# # Cpp11BracedListStyle: false
+# # DeriveLineEnding: true
+# # DerivePointerAlignment: false
+# # DisableFormat: false
+# # ExperimentalAutoDetectBinPacking: false
+# # FixNamespaceComments: false
+# ForEachMacros:
+# - foreach
+# - Q_FOREACH
+# - BOOST_FOREACH
+# # IncludeBlocks: Preserve
+# # IncludeCategories:
+# # - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
+# # Priority: 2
+# # SortPriority: 0
+# # - Regex: '^(<|"(gtest|gmock|isl|json)/)'
+# # Priority: 3
+# # SortPriority: 0
+# # - Regex: ".*"
+# # Priority: 1
+# # SortPriority: 0
+# # IncludeIsMainRegex: "(Test)?$"
+# # IncludeIsMainSourceRegex: ""
+# IndentCaseLabels: true
+# IndentGotoLabels: true
+# IndentPPDirectives: None
+# IndentWidth: 4
+# # IndentWrappedFunctionNames: false
+# # JavaScriptQuotes: Leave
+# # JavaScriptWrapImports: true
+# KeepEmptyLinesAtTheStartOfBlocks: true
+# # MacroBlockBegin: ""
+# # MacroBlockEnd: ""
+# MaxEmptyLinesToKeep: 1
+# # NamespaceIndentation: None
+# # ObjCBinPackProtocolList: Auto
+# # ObjCBlockIndentWidth: 2
+# # ObjCSpaceAfterProperty: true
+# # ObjCSpaceBeforeProtocolList: false
+# # PenaltyBreakAssignment: 2
+# # PenaltyBreakBeforeFirstCallParameter: 19
+# # PenaltyBreakComment: 300
+# # PenaltyBreakFirstLessLess: 120
+# # PenaltyBreakString: 1000
+# # PenaltyBreakTemplateDeclaration: 10
+# # PenaltyExcessCharacter: 1000000
+# # PenaltyReturnTypeOnItsOwnLine: 200
+# PointerAlignment: Left
+# # ReflowComments: true
+# SortIncludes: true
+# # SortUsingDeclarations: true
+# SpaceAfterCStyleCast: false
+# SpaceAfterLogicalNot: false
+# SpaceAfterTemplateKeyword: false
+# SpaceBeforeAssignmentOperators: true
+# SpaceBeforeCpp11BracedList: false
+# SpaceBeforeCtorInitializerColon: true
+# SpaceBeforeInheritanceColon: true
+# SpaceBeforeParens: ControlStatements
+# SpaceBeforeRangeBasedForLoopColon: true
+# SpaceInEmptyBlock: true
+# SpaceInEmptyParentheses: false
+# SpacesBeforeTrailingComments: 1
+# SpacesInAngles: false
+# SpacesInConditionalStatement: false
+# SpacesInContainerLiterals: true
+# SpacesInCStyleCastParentheses: false
+# SpacesInParentheses: false
+# SpacesInSquareBrackets: false
+# SpaceBeforeSquareBrackets: false
+# Standard: Latest
+# StatementMacros:
+# - Q_UNUSED
+# - QT_REQUIRE_VERSION
+# TypenameMacros:
+# - optimize
+# - noret
+# - weak
+# - weak_alias
+# # TabWidth: 8
+# UseCRLF: false
+# UseTab: Never
+# # ---
--- /dev/null
+#ifndef __LUNAIX_MULDIV64_H
+#define __LUNAIX_MULDIV64_H
+
+#include <lunaix/spike.h>
+#include <lunaix/types.h>
+
+#define do_udiv64(n, base) \
+ ({ \
+ unsigned long __upper, __low, __high, __mod, __base; \
+ __base = (base); \
+ if (__builtin_constant_p(__base) && is_pot(__base)) { \
+ __mod = n & (__base - 1); \
+ n >>= ILOG2(__base); \
+ } else { \
+ asm("" : "=a"(__low), "=d"(__high) : "A"(n)); \
+ __upper = __high; \
+ if (__high) { \
+ __upper = __high % (__base); \
+ __high = __high / (__base); \
+ } \
+ asm("divl %2" \
+ : "=a"(__low), "=d"(__mod) \
+ : "rm"(__base), "0"(__low), "1"(__upper)); \
+ asm("" : "=A"(n) : "a"(__low), "d"(__high)); \
+ } \
+ __mod; \
+ })
+
+static inline u64_t
+udiv64(u64_t n, unsigned int base)
+{
+ do_udiv64(n, base);
+
+ return n;
+}
+
+static inline unsigned int
+umod64(u64_t n, unsigned int base)
+{
+ return do_udiv64(n, base);
+}
+
+#endif /* __LUNAIX_MULDIV64_H */
if (!hba->base[HBA_RIS])
return;
- u32_t port_num = 31 - __builtin_clz(hba->base[HBA_RIS]);
+ u32_t port_num = 31 - clz(hba->base[HBA_RIS]);
struct hba_port* port = hba->ports[port_num];
struct hba_cmd_context* cmdctx = &port->cmdctx;
u32_t processed = port->regs[HBA_RPxCI] ^ cmdctx->tracked_ci;
goto done;
}
- u32_t slot = 31 - __builtin_clz(processed);
+ u32_t slot = 31 - clz(processed);
struct hba_cmd_state* cmdstate = cmdctx->issued[slot];
if (!cmdstate) {
static struct device_def devnull_def = {
.name = "null",
.class = DEVCLASSV(DEVIF_NON, DEVFN_PSEUDO, DEV_NULL, DEV_BUILTIN_NULL),
- .init = pdev_nulldev_init
-};
+ .init = pdev_nulldev_init};
EXPORT_DEVICE(nulldev, &devnull_def, load_onboot);
static struct device_def devzero_def = {
.name = "zero",
.class = DEVCLASSV(DEVIF_NON, DEVFN_PSEUDO, DEV_ZERO, DEV_BUILTIN_ZERO),
- .init = pdev_zerodev_init
-};
+ .init = pdev_zerodev_init};
EXPORT_DEVICE(zerodev, &devzero_def, load_onboot);
#include <hal/serial.h>
+#define lock_sdev(sdev) device_lock((sdev)->dev)
+#define unlock_sdev(sdev) device_unlock((sdev)->dev)
+#define unlock_and_wait(sdev, wq) \
+ ({ \
+ unlock_sdev(sdev); \
+ pwait(&(sdev)->wq); \
+ lock_sdev(sdev); \
+ })
+
static DEFINE_LLIST(serial_devs);
static int serial_idx = 0;
int
serial_readone_nowait(struct serial_dev* sdev, u8_t* val)
{
- device_lock(sdev->dev);
+ lock_sdev(sdev);
int rd_len = rbuffer_get(&sdev->rxbuf, (char*)val);
- device_unlock(sdev->dev);
+ unlock_sdev(sdev);
return rd_len;
}
void
serial_readone(struct serial_dev* sdev, u8_t* val)
{
- device_lock(sdev->dev);
+ lock_sdev(sdev);
mark_device_doing_read(sdev->dev);
while (!rbuffer_get(&sdev->rxbuf, (char*)val)) {
- pwait(&sdev->wq_rxdone);
+ unlock_and_wait(sdev, wq_rxdone);
}
- device_unlock(sdev->dev);
+ unlock_sdev(sdev);
}
size_t
serial_readbuf(struct serial_dev* sdev, u8_t* buf, size_t len)
{
- device_lock(sdev->dev);
+ lock_sdev(sdev);
mark_device_doing_read(sdev->dev);
size_t rdlen;
while (!(rdlen = rbuffer_gets(&sdev->rxbuf, (char*)buf, len))) {
- pwait(&sdev->wq_rxdone);
+ unlock_and_wait(sdev, wq_rxdone);
}
- device_unlock(sdev->dev);
+ unlock_sdev(sdev);
return rdlen;
}
int
serial_readbuf_nowait(struct serial_dev* sdev, u8_t* buf, size_t len)
{
- device_lock(sdev->dev);
+ lock_sdev(sdev);
mark_device_doing_read(sdev->dev);
int rdlen = rbuffer_gets(&sdev->rxbuf, (char*)buf, len);
- device_unlock(sdev->dev);
+ unlock_sdev(sdev);
return rdlen;
}
int
serial_writebuf(struct serial_dev* sdev, u8_t* buf, size_t len)
{
- device_lock(sdev->dev);
+ lock_sdev(sdev);
mark_device_doing_write(sdev->dev);
goto done;
}
- pwait(&sdev->wq_txdone);
+ unlock_and_wait(sdev, wq_txdone);
done:
int rdlen = sdev->wr_len;
- device_unlock(sdev->dev);
+ unlock_sdev(sdev);
return rdlen;
}
int
serial_writebuf_nowait(struct serial_dev* sdev, u8_t* buf, size_t len)
{
- device_lock(sdev->dev);
+ lock_sdev(sdev);
mark_device_doing_write(sdev->dev);
sdev->write(sdev, buf, len);
int rdlen = sdev->wr_len;
- device_unlock(sdev->dev);
+ unlock_sdev(sdev);
return rdlen;
}
return serial_readbuf(serial_device(dev), &((u8_t*)buf)[offset], len);
}
+static int
+__serial_read_async(struct device* dev, void* buf, size_t offset, size_t len)
+{
+ return serial_readbuf_nowait(
+ serial_device(dev), &((u8_t*)buf)[offset], len);
+}
+
static int
__serial_read_page(struct device* dev, void* buf, size_t offset)
{
return serial_writebuf(serial_device(dev), &((u8_t*)buf)[offset], len);
}
+static int
+__serial_write_async(struct device* dev, void* buf, size_t offset, size_t len)
+{
+ return serial_writebuf_nowait(
+ serial_device(dev), &((u8_t*)buf)[offset], len);
+}
+
static int
__serial_write_page(struct device* dev, void* buf, size_t offset)
{
static struct device_def devrandx86_def = {
.name = "x86 On-Chip RNG",
.class = DEVCLASS(DEVIF_SOC, DEVFN_CHAR, DEV_RNG),
- .init = pdev_randdev_init
-};
+ .init = pdev_randdev_init};
EXPORT_DEVICE(randdev, &devrandx86_def, load_onboot);
\ No newline at end of file
twimap_printf(mapping, "name: %s\n", rtc->name);
twimap_printf(mapping, "frequency: %dHz\n", rtc->base_freq);
twimap_printf(mapping, "ticks count: %d\n", rtc->get_counts(rtc));
- twimap_printf(
- mapping, "ticking: %s\n", (rtc->state & RTC_STATE_MASKED) ? "no" : "yes");
+ twimap_printf(mapping,
+ "ticking: %s\n",
+ (rtc->state & RTC_STATE_MASKED) ? "no" : "yes");
datetime_t dt;
rtc->get_walltime(rtc, &dt);
twimap_printf(
- mapping, "recorded date: %d/%d/%d\n", dt.year, dt.month, dt.day);
+ mapping, "recorded date: %d/%d/%d\n", dt.year, dt.month, dt.day);
twimap_printf(
- mapping, "recorded time: %d:%d:%d\n", dt.hour, dt.minute, dt.second);
+ mapping, "recorded time: %d:%d:%d\n", dt.hour, dt.minute, dt.second);
twimap_printf(mapping, "recorded weekday: %d\n", dt.weekday);
}
#define CTRL_MNEMO(chr) (chr - 'A' + 1)
-static inline size_t
+static inline int
__ansi_actcontrol(struct term* termdev, struct linebuffer* lbuf, char chr)
{
struct rbuffer* cooked = lbuf->next;
return rbuffer_put(cooked, chr);
}
-struct term_lcntl ansi_line_controller = { .process_and_put =
- __ansi_actcontrol };
\ No newline at end of file
+struct term_lcntl ansi_line_controller = {.process_and_put = __ansi_actcontrol};
\ No newline at end of file
lbuf->sflags |= LSTATE_SIGRAISE;
}
-static inline int
-lcntl_invoke_slaves(struct term* tdev, struct linebuffer* lbuf, char c)
-{
- int allow_more = 0;
- struct term_lcntl *lcntl, *n;
- llist_for_each(lcntl, n, &tdev->lcntl_stack, lcntls)
- {
- allow_more = lcntl->process_and_put(tdev, lbuf, c);
- if (!allow_more) {
- break;
- }
-
- line_flip(lbuf);
- }
-
- return allow_more;
-}
-
-static inline int optimize("ipa-cp-clone")
+static inline int must_inline optimize("-fipa-cp-clone")
lcntl_transform_seq(struct term* tdev, struct linebuffer* lbuf, bool out)
{
struct rbuffer* raw = lbuf->current;
char c;
bool should_flush = false;
+ int (*lcntl_slave_put)(struct term*, struct linebuffer*, char) =
+ tdev->lcntl->process_and_put;
+
#define EOL tdev->cc[_VEOL]
#define EOF tdev->cc[_VEOF]
#define ERASE tdev->cc[_VERASE]
raise_sig(tdev, lbuf, SIGSTOP);
} else if (c == ERASE) {
rbuffer_erase(cooked);
+ } else if (c == KILL) {
+ // TODO shrink the rbuffer
} else {
goto keep;
}
}
put_char:
- allow_more = rbuffer_put(cooked, c);
- }
-
- if (out || (_lf & _IEXTEN)) {
- line_flip(lbuf);
- lcntl_invoke_slaves(tdev, lbuf, c);
+ if (!out && (_lf & _IEXTEN) && lcntl_slave_put) {
+ allow_more = lcntl_slave_put(tdev, lbuf, c);
+ } else {
+ allow_more = rbuffer_put(cooked, c);
+ }
}
if (should_flush && !(_lf & _NOFLSH)) {
term_flush(tdev);
}
+ line_flip(lbuf);
+
return i;
}
device_lock(dev);
switch (req) {
- case TIOCSPGRP: {
- pid_t pgid = va_arg(args, pid_t);
- if (pgid < 0) {
- err = EINVAL;
- goto done;
- }
- term->fggrp = pgid;
- break;
- }
- case TIOCGPGRP:
- return term->fggrp;
- case TDEV_TCPUSHLC: {
- u32_t lcntl_idx = va_arg(args, u32_t);
- struct term_lcntl* lcntl = term_get_lcntl(lcntl_idx);
-
- if (!lcntl) {
- err = EINVAL;
- goto done;
- }
-
- term_push_lcntl(term, lcntl);
- break;
- }
- case TDEV_TCPOPLC:
- term_pop_lcntl(term);
- break;
- case TDEV_TCSETCHDEV: {
- int fd = va_arg(args, int);
- struct v_fd* vfd;
-
- if (vfs_getfd(fd, &vfd)) {
- err = EINVAL;
- goto done;
- }
-
- struct device* cdev = device_cast(vfd->file->inode->data);
- if (!cdev) {
- err = ENOTDEV;
- goto done;
- }
- if (cdev->dev_type != DEV_IFSEQ) {
- err = EINVAL;
- goto done;
+ case TIOCSPGRP: {
+ pid_t pgid = va_arg(args, pid_t);
+ if (pgid < 0) {
+ err = EINVAL;
+ goto done;
+ }
+ term->fggrp = pgid;
+ break;
}
+ case TIOCGPGRP:
+ return term->fggrp;
+ case TDEV_TCSETCHDEV: {
+ int fd = va_arg(args, int);
+ struct v_fd* vfd;
+
+ if (vfs_getfd(fd, &vfd)) {
+ err = EINVAL;
+ goto done;
+ }
- term_bind(term, cdev);
- break;
- }
- case TDEV_TCGETCHDEV: {
- struct dev_info* devinfo = va_arg(args, struct dev_info*);
+ struct device* cdev = device_cast(vfd->file->inode->data);
+ if (!cdev) {
+ err = ENOTDEV;
+ goto done;
+ }
+ if (cdev->dev_type != DEV_IFSEQ) {
+ err = EINVAL;
+ goto done;
+ }
- if (!term->chdev) {
- err = ENODEV;
- goto done;
+ term_bind(term, cdev);
+ break;
}
+ case TDEV_TCGETCHDEV: {
+ struct dev_info* devinfo = va_arg(args, struct dev_info*);
- if (devinfo) {
- device_populate_info(term->chdev, devinfo);
- }
- break;
- }
- case TDEV_TCGETATTR: {
- struct _termios* tios = va_arg(args, struct _termios*);
- *tios = (struct _termios){.c_oflag = term->oflags,
- .c_iflag = term->iflags,
- .c_lflag = term->lflags};
- memcpy(tios->c_cc, term->cc, _NCCS * sizeof(cc_t));
- tios->c_baud = term->iospeed;
- } break;
- case TDEV_TCSETATTR: {
- struct _termios* tios = va_arg(args, struct _termios*);
- term->iflags = tios->c_iflag;
- term->oflags = tios->c_oflag;
- term->lflags = tios->c_lflag;
- memcpy(term->cc, tios->c_cc, _NCCS * sizeof(cc_t));
-
- if (tios->c_baud != term->iospeed) {
- term->iospeed = tios->c_baud;
- if (!term->chdev_ops.set_speed) {
+ if (!term->chdev) {
+ err = ENODEV;
goto done;
}
- term->chdev_ops.set_speed(term->chdev, tios->c_baud);
+ if (devinfo) {
+ device_populate_info(term->chdev, devinfo);
+ }
+ break;
}
- } break;
- default:
- err = EINVAL;
- goto done;
+ case TDEV_TCGETATTR: {
+ struct _termios* tios = va_arg(args, struct _termios*);
+ *tios = (struct _termios){.c_oflag = term->oflags,
+ .c_iflag = term->iflags,
+ .c_lflag = term->lflags};
+ memcpy(tios->c_cc, term->cc, _NCCS * sizeof(cc_t));
+ tios->c_baud = term->iospeed;
+ } break;
+ case TDEV_TCSETATTR: {
+ struct _termios* tios = va_arg(args, struct _termios*);
+ term->iflags = tios->c_iflag;
+ term->oflags = tios->c_oflag;
+ term->lflags = tios->c_lflag;
+ memcpy(term->cc, tios->c_cc, _NCCS * sizeof(cc_t));
+
+ if (tios->c_baud != term->iospeed) {
+ term->iospeed = tios->c_baud;
+ if (!term->chdev_ops.set_speed) {
+ goto done;
+ }
+
+ term->chdev_ops.set_speed(term->chdev, tios->c_baud);
+ }
+ } break;
+ default:
+ err = EINVAL;
+ goto done;
}
done:
lbuf_ref_t current = ref_current(&tdev->line_out);
size_t wrsz = 0;
while (wrsz < len) {
- wrsz += rbuffer_puts(deref(current), &((char*)buf)[offset + wrsz],
- len - wrsz);
+ wrsz += rbuffer_puts(
+ deref(current), &((char*)buf)[offset + wrsz], len - wrsz);
+
if (rbuffer_full(deref(current))) {
term_flush(tdev);
}
cont = term_read(tdev);
}
- rdsz += rbuffer_gets(deref(current), &((char*)buf)[offset + rdsz],
- len - rdsz);
+ rdsz += rbuffer_gets(
+ deref(current), &((char*)buf)[offset + rdsz], len - rdsz);
}
return rdsz;
terminal->dev->ops.read = tdev_do_read;
terminal->dev->ops.write = tdev_do_write;
- llist_init_head(&terminal->lcntl_stack);
+ // TODO choice of lcntl can be flexible
+ terminal->lcntl = line_controls[ANSI_LCNTL];
+
line_alloc(&terminal->line_in, 1024);
line_alloc(&terminal->line_out, 1024);
return 0;
}
-struct term_lcntl*
-term_get_lcntl(u32_t lcntl_index)
-{
- if (lcntl_index >= LCNTL_TABLE_LEN) {
- return NULL;
- }
-
- struct term_lcntl* lcntl_template = line_controls[lcntl_index];
- struct term_lcntl* lcntl_instance = valloc(sizeof(struct term_lcntl));
-
- if (!lcntl_instance) {
- return NULL;
- }
-
- lcntl_instance->process_and_put = lcntl_template->process_and_put;
-
- return lcntl_instance;
-}
-
-int
-term_push_lcntl(struct term* term, struct term_lcntl* lcntl)
-{
- device_lock(term->dev);
-
- llist_append(&term->lcntl_stack, &lcntl->lcntls);
-
- device_unlock(term->dev);
-
- return 0;
-}
-
-int
-term_pop_lcntl(struct term* term)
-{
- if (term->lcntl_stack.prev == &term->lcntl_stack) {
- return 0;
- }
-
- device_lock(term->dev);
-
- struct term_lcntl* lcntl =
- list_entry(term->lcntl_stack.prev, struct term_lcntl, lcntls);
- llist_delete(term->lcntl_stack.prev);
-
- vfree(lcntl);
-
- device_unlock(term->dev);
-
- return 1;
-}
-
void
line_alloc(struct linebuffer* lbf, size_t sz_hlf)
{
char* inbuffer = line_in->current->buffer;
size_t min = tdev->cc[_VMIN] - 1;
- size_t sz = chdev->ops.read(chdev, inbuffer, 0, max_lb_sz);
+ size_t sz = chdev->ops.read_async(chdev, inbuffer, 0, max_lb_sz);
time_t t = clock_systime(), dt = 0;
time_t expr = (tdev->cc[_VTIME] * 100) - 1;
max_lb_sz -= sz;
// TODO pass a flags to read to indicate it is non blocking ops
- sz +=
- chdev->ops.read(chdev, inbuffer, sz, max_lb_sz);
+ sz += chdev->ops.read_async(chdev, inbuffer, sz, max_lb_sz);
}
rbuffer_puts(line_in->next, inbuffer, sz);
}
static int
-do_read_raw_canno(struct term* tdev) {
+do_read_raw_canno(struct term* tdev)
+{
struct device* chdev = tdev->chdev;
struct linebuffer* line_in = &tdev->line_in;
struct rbuffer* current_buf = line_in->current;
term_read_noncano(struct term* tdev)
{
struct device* chdev = tdev->chdev;
- return do_read_raw(tdev);;
+ return do_read_raw(tdev);
+ ;
}
static int
#ifndef __LUNAIX_ACPI_ACPI_H
#define __LUNAIX_ACPI_ACPI_H
-#include <stddef.h>
-#include <stdint.h>
-
#include "fadt.h"
#include "madt.h"
#include "mcfg.h"
struct linebuffer
{
- struct rbuffer *next;
- struct rbuffer *current;
+ struct rbuffer* next;
+ struct rbuffer* current;
short sflags;
short sz_hlf;
};
struct term_lcntl
{
- struct llist_header lcntls;
struct term* term;
- size_t (*process_and_put)(struct term*, struct linebuffer*, char);
+ int (*process_and_put)(struct term*, struct linebuffer*, char);
};
struct term
{
struct device* dev;
struct device* chdev;
- struct llist_header lcntl_stack;
+ struct term_lcntl* lcntl;
struct linebuffer line_out;
struct linebuffer line_in;
pid_t fggrp;
term_get_lcntl(u32_t lcntl_index);
static inline void
-line_flip(struct linebuffer* lbf) {
+line_flip(struct linebuffer* lbf)
+{
struct rbuffer* tmp = lbf->current;
lbf->current = lbf->next;
lbf->next = tmp;
#ifndef __LUNAIX_STRFMT_H
#define __LUNAIX_STRFMT_H
#include <stdarg.h>
-#include <stddef.h>
-size_t
-ksnprintfv(char* buffer, const char* fmt, size_t max_len, va_list vargs);
+unsigned long
+ksnprintfv(char* buffer, const char* fmt, unsigned long max_len, va_list vargs);
-size_t
+unsigned long
ksprintf(char* buffer, char* fmt, ...);
-size_t
-ksnprintf(char* buffer, size_t n, char* fmt, ...);
+unsigned long
+ksnprintf(char* buffer, unsigned long n, char* fmt, ...);
#endif /* __LUNAIX_STRFMT_H */
#ifndef __LUNAIX_STRING_H
#define __LUNAIX_STRING_H
-#include <stddef.h>
-
int
-memcmp(const void* dest, const void* src, size_t size);
+memcmp(const void* dest, const void* src, unsigned long size);
void*
-memcpy(void* dest, const void* src, size_t size);
+memcpy(void* dest, const void* src, unsigned long size);
void*
-memmove(void* dest, const void* src, size_t size);
+memmove(void* dest, const void* src, unsigned long size);
void*
-memset(void* dest, int val, size_t size);
+memset(void* dest, int val, unsigned long size);
-size_t
+unsigned long
strlen(const char* str);
char*
strcpy(char* dest, const char* src);
-size_t
-strnlen(const char* str, size_t max_len);
+unsigned long
+strnlen(const char* str, unsigned long max_len);
char*
-strncpy(char* dest, const char* src, size_t n);
+strncpy(char* dest, const char* src, unsigned long n);
const char*
strchr(const char* str, int character);
#define weak __attribute__((weak))
#define noret __attribute__((noreturn))
#define optimize(opt) __attribute__((optimize(opt)))
+#define must_inline __attribute__((always_inline))
+
+#define clz(bits) __builtin_clz(bits)
+#define sadd_overflow(a, b, of) __builtin_sadd_overflow(a, b, of)
+#define umul_overflow(a, b, of) __builtin_umul_overflow(a, b, of)
+#define offsetof(f, m) __builtin_offsetof(f, m)
#define prefetch_rd(ptr, ll) __builtin_prefetch((ptr), 0, ll)
#define prefetch_wr(ptr, ll) __builtin_prefetch((ptr), 1, ll)
int (*read)(struct device*, void*, off_t, size_t);
int (*write)(struct device*, void*, off_t, size_t);
+ int (*read_async)(struct device*, void*, off_t, size_t);
+ int (*write_async)(struct device*, void*, off_t, size_t);
int (*read_page)(struct device*, void*, off_t);
int (*write_page)(struct device*, void*, off_t);
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define is_pot(val) (((val) != 0) || ((val) & ((val)-1)) == 0)
+
/**
* @brief Fast log base 2 for integer, utilizing constant unfolding.
* Adopted from
: ((x) & (1ul << 2)) ? 2 \
: ((x) & (1ul << 1)) ? 1 \
: 0) \
- : (31 - __builtin_clz(x)))
+ : (31 - clz(x)))
#ifndef __LUNAIXOS_NASSERT__
#define assert(cond) \
void
__assert_fail(const char* expr, const char* file, unsigned int line)
- __attribute__((noinline, noreturn));
+ __attribute__((noinline, noreturn));
#else
#define assert(cond) (void)(cond); // assert nothing
#define assert_msg(cond, msg) (void)(cond); // assert nothing
#include <lunaix/compiler.h>
#include <stdarg.h>
-#include <stddef.h>
#include <usr/lunaix/types.h>
#define PACKED __attribute__((packed))
typedef unsigned long long u64_t;
typedef unsigned long ptr_t;
-typedef signed long ssize_t;
typedef int pid_t;
-typedef unsigned long size_t;
-typedef unsigned long off_t;
+typedef signed long ssize_t;
+// typedef unsigned long size_t;
+// typedef unsigned long off_t;
typedef unsigned int cpu_t;
typedef int pid_t;
-typedef unsigned long size_t;
+typedef __SIZE_TYPE__ size_t;
-typedef unsigned long off_t;
+typedef __SIZE_TYPE__ off_t;
typedef unsigned int ino_t;
%.S.o: %.S
$(call status_,AS,$<)
- @$(CC) $(kinc_opts) -c $< -o $@
+ @$(CC) $(CFLAGS) $(kinc_opts) -c $< -o $@
%.c.o: %.c
$(call status_,CC,$<)
#include <lunaix/status.h>
#include <lunaix/syslog.h>
+#include <sys/muldiv64.h>
+
#include <lib/crc.h>
#define GPT_BLKSIZE 512
}
// Convert UEFI's 512B LB representation into local LBA range.
- u64_t slba_local =
- (ent->start_lba * GPT_BLKSIZE) / (u64_t)bdev->blk_size;
- u64_t elba_local = (ent->end_lba * GPT_BLKSIZE) / (u64_t)bdev->blk_size;
+ u64_t slba_local = udiv64(ent->start_lba * GPT_BLKSIZE, bdev->blk_size);
+ u64_t elba_local = udiv64(ent->end_lba * GPT_BLKSIZE, bdev->blk_size);
kprintf("%s: guid part#%d: %d..%d",
bdev->bdev_id,
__btrie_traversal(struct btrie* root, u32_t index, int options)
{
index = index >> root->truncated;
- u32_t lz = index ? ROUNDDOWN(31 - __builtin_clz(index), BTRIE_BITS) : 0;
+ u32_t lz = index ? ROUNDDOWN(31 - clz(index), BTRIE_BITS) : 0;
u32_t bitmask = ((1 << BTRIE_BITS) - 1) << lz;
u32_t i = 0;
struct btrie_node* tree = root->btrie_root;
if ((inode->itype & F_FILE)) {
errno = ENOTDIR;
} else {
- struct dir_context dctx =
- (struct dir_context){ .cb_data = dent,
- .index = dent->d_offset,
- .read_complete_callback =
- __vfs_readdir_callback };
+ struct dir_context dctx = (struct dir_context){
+ .cb_data = dent,
+ .index = dent->d_offset,
+ .read_complete_callback = __vfs_readdir_callback};
errno = 1;
if (dent->d_offset == 0) {
__vfs_readdir_callback(&dctx, vfs_dot.value, vfs_dot.len, DT_DIR);
int fpos = file->f_pos;
switch (options) {
case FSEEK_CUR:
- overflow = __builtin_sadd_overflow((int)file->f_pos, offset, &fpos);
+ overflow = sadd_overflow((int)file->f_pos, offset, &fpos);
break;
case FSEEK_END:
- overflow =
- __builtin_sadd_overflow((int)file->inode->fsize, offset, &fpos);
+ overflow = sadd_overflow((int)file->inode->fsize, offset, &fpos);
break;
case FSEEK_SET:
fpos = offset;
return DO_STATUS(errno);
}
-__DEFINE_LXSYSCALL4(int,
- readlinkat,
- int,
- dirfd,
- const char*,
- pathname,
- char*,
- buf,
- size_t,
- size)
+__DEFINE_LXSYSCALL4(
+ int, readlinkat, int, dirfd, const char*, pathname, char*, buf, size_t, size)
{
int errno;
struct v_fd* fd_s;
return DO_STATUS(errno);
}
-__DEFINE_LXSYSCALL2(int,
- symlink,
- const char*,
- pathname,
- const char*,
- link_target)
+__DEFINE_LXSYSCALL2(
+ int, symlink, const char*, pathname, const char*, link_target)
{
int errno;
struct v_dnode *dnode, *file;
struct v_inode* vino = fds->file->inode;
struct device* fdev = vino->sb->dev;
- *stat = (struct file_stat){ .st_ino = vino->id,
- .st_blocks = vino->lb_usage,
- .st_size = vino->fsize,
- .mode = vino->itype,
- .st_ioblksize = PG_SIZE,
- .st_blksize = vino->sb->blksize };
+ *stat = (struct file_stat){.st_ino = vino->id,
+ .st_blocks = vino->lb_usage,
+ .st_size = vino->fsize,
+ .mode = vino->itype,
+ .st_ioblksize = PG_SIZE,
+ .st_blksize = vino->sb->blksize};
if (VFS_DEVFILE(vino->itype)) {
struct device* rdev = (struct device*)vino->data;
goto done;
}
- stat->st_rdev = (dev_t){ .meta = rdev->ident.fn_grp,
- .unique = rdev->ident.unique,
- .index = rdev->dev_uid };
+ stat->st_rdev = (dev_t){.meta = rdev->ident.fn_grp,
+ .unique = rdev->ident.unique,
+ .index = rdev->dev_uid};
}
if (fdev) {
- stat->st_dev = (dev_t){ .meta = fdev->ident.fn_grp,
- .unique = fdev->ident.unique,
- .index = fdev->dev_uid };
+ stat->st_dev = (dev_t){.meta = fdev->ident.fn_grp,
+ .unique = fdev->ident.unique,
+ .index = fdev->dev_uid};
}
done:
#define CLASS_LEN(class) (sizeof(class) / sizeof(class[0]))
-static char piles_names[][PILE_NAME_MAXLEN] = {
- "valloc_8", "valloc_16", "valloc_32", "valloc_64",
- "valloc_128", "valloc_256", "valloc_512", "valloc_1k",
- "valloc_2k", "valloc_4k", "valloc_8k"
-};
-
-static char piles_names_dma[][PILE_NAME_MAXLEN] = {
- "valloc_dma_128", "valloc_dma_256", "valloc_dma_512",
- "valloc_dma_1k", "valloc_dma_2k", "valloc_dma_4k"
-};
+static char piles_names[][PILE_NAME_MAXLEN] = {"valloc_8",
+ "valloc_16",
+ "valloc_32",
+ "valloc_64",
+ "valloc_128",
+ "valloc_256",
+ "valloc_512",
+ "valloc_1k",
+ "valloc_2k",
+ "valloc_4k",
+ "valloc_8k"};
+
+static char piles_names_dma[][PILE_NAME_MAXLEN] = {"valloc_dma_128",
+ "valloc_dma_256",
+ "valloc_dma_512",
+ "valloc_dma_1k",
+ "valloc_dma_2k",
+ "valloc_dma_4k"};
static struct cake_pile* piles[CLASS_LEN(piles_names)];
static struct cake_pile* piles_dma[CLASS_LEN(piles_names_dma)];
for (size_t i = 0; i < CLASS_LEN(piles_names_dma); i++) {
int size = 1 << (i + 7);
piles_dma[i] = cake_new_pile(
- piles_names_dma[i], size, size > 1024 ? 4 : 1, PILE_ALIGN_CACHE);
+ piles_names_dma[i], size, size > 1024 ? 4 : 1, PILE_ALIGN_CACHE);
}
}
vcalloc(unsigned int size, unsigned int count)
{
unsigned int alloc_size;
- if (__builtin_umul_overflow(size, count, &alloc_size)) {
+ if (umul_overflow(size, count, &alloc_size)) {
return 0;
}
struct sigact* prev_working = psig->inprogress;
sigset_t mask = psig->sig_mask | (prev_working ? prev_working->sa_mask : 0);
- int sig_selected = 31 - __builtin_clz(psig->sig_pending & ~mask);
+ int sig_selected = 31 - clz(psig->sig_pending & ~mask);
sigset_clear(psig->sig_pending, sig_selected);
}
struct proc_sig* sigframe =
- (struct proc_sig*)((ustack - sizeof(struct proc_sig)) & ~0xf);
+ (struct proc_sig*)((ustack - sizeof(struct proc_sig)) & ~0xf);
sigframe->sig_num = sig_selected;
sigframe->sigact = action->sa_actor;
return 0;
}
-__DEFINE_LXSYSCALL3(int,
- sigprocmask,
- int,
- how,
- const sigset_t,
- *set,
- sigset_t,
- *oldset)
+__DEFINE_LXSYSCALL3(
+ int, sigprocmask, int, how, const sigset_t, *set, sigset_t, *oldset)
{
struct sighail* sh = &__current->sigctx;
*oldset = sh->sig_mask;
#define FLAG_ALT2 (1 << 8)
#define FLAG_CAPS (1 << 9)
-size_t
-ksnprintfv(char* buffer, const char* fmt, size_t max_len, va_list vargs)
+unsigned long
+ksnprintfv(char* buffer, const char* fmt, unsigned long max_len, va_list vargs)
{
// This sprintf just a random implementation I found it on Internet . lol.
// Of course, with some modifications for porting to LunaixOS :)
return ptr;
}
-size_t
+unsigned long
ksprintf(char* buffer, char* fmt, ...)
{
va_list args;
va_start(args, fmt);
- size_t len = ksnprintfv(buffer, fmt, 0, args);
+ unsigned long len = ksnprintfv(buffer, fmt, 0, args);
va_end(args);
return len;
}
-size_t
-ksnprintf(char* buffer, size_t n, char* fmt, ...)
+unsigned long
+ksnprintf(char* buffer, unsigned long n, char* fmt, ...)
{
va_list args;
va_start(args, fmt);
- size_t len = ksnprintfv(buffer, fmt, n, args);
+ unsigned long len = ksnprintfv(buffer, fmt, n, args);
va_end(args);
return len;
}
\ No newline at end of file
#define __LUNAIX_LIBC
-#include <stddef.h>
#include <klibc/stdlib.h>
+#include <lunaix/types.h>
char base_char[] = "0123456789abcdefghijklmnopqrstuvwxyz";
#include <lunaix/types.h>
void*
-memcpy(void* dest, const void* src, size_t num)
+memcpy(void* dest, const void* src, unsigned long num)
{
if (!num)
return dest;
}
void*
-memmove(void* dest, const void* src, size_t num)
+memmove(void* dest, const void* src, unsigned long num)
{
u8_t* dest_ptr = (u8_t*)dest;
const u8_t* src_ptr = (const u8_t*)src;
if (dest_ptr < src_ptr) {
- for (size_t i = 0; i < num; i++) {
+ for (unsigned long i = 0; i < num; i++) {
*(dest_ptr + i) = *(src_ptr + i);
}
} else {
- for (size_t i = num; i != 0; i--) {
+ for (unsigned long i = num; i != 0; i--) {
*(dest_ptr + i - 1) = *(src_ptr + i - 1);
}
}
}
void*
-memset(void* ptr, int value, size_t num)
+memset(void* ptr, int value, unsigned long num)
{
asm volatile("movl %1, %%edi\n"
"rep stosb\n" ::"c"(num),
}
int
-memcmp(const void* ptr1, const void* ptr2, size_t num)
+memcmp(const void* ptr1, const void* ptr2, unsigned long num)
{
u8_t* p1 = (u8_t*)ptr1;
u8_t* p2 = (u8_t*)ptr2;
- for (size_t i = 0; i < num; i++) {
+ for (unsigned long i = 0; i < num; i++) {
int diff = *(p1 + i) - *(p2 + i);
if (diff != 0) {
return diff;
#include <klibc/string.h>
+#include <lunaix/types.h>
const char*
strchr(const char* str, int character)
}
char*
-strncpy(char* dest, const char* src, size_t n)
+strncpy(char* dest, const char* src, unsigned long n)
{
char c;
unsigned int i = 0;
#include <klibc/string.h>
-size_t
+unsigned long
strlen(const char* str)
{
- size_t len = 0;
+ unsigned long len = 0;
while (str[len])
len++;
return len;
}
-size_t
-strnlen(const char* str, size_t max_len)
+unsigned long
+strnlen(const char* str, unsigned long max_len)
{
- size_t len = 0;
+ unsigned long len = 0;
while (str[len] && len <= max_len)
len++;
return len;
void
strrtrim(char* str)
{
- size_t l = strlen(str);
- while (l < (size_t)-1) {
+ unsigned long l = strlen(str);
+ while (l < (unsigned long)-1) {
char c = str[l];
if (!c || WS_CHAR(c)) {
l--;
char*
strltrim_safe(char* str)
{
- size_t l = 0;
+ unsigned long l = 0;
char c = 0;
while ((c = str[l]) && WS_CHAR(c)) {
l++;
-d trace:ide_dma_cb \
-vga std,retrace=precise \
-serial telnet::12345,server,nowait\
- -drive id=disk,file="machine/disk0.vdi",if=none \
-drive id=cdrom,file="$(1)",readonly=on,if=none,format=raw \
-device ahci,id=ahci \
- -device ide-hd,drive=disk,bus=ahci.0 \
- -device ide-cd,drive=cdrom,bus=ahci.1 \
+ -device ide-cd,drive=cdrom,bus=ahci.0 \
-monitor telnet::$(QEMU_MON_PORT),server,nowait &
\ No newline at end of file
-CC := i686-elf-gcc
-AS := i686-elf-as
-AR := i686-elf-ar
+CC := $(CX_PREFIX)gcc
+CC := $(CX_PREFIX)gcc
+AS := $(CX_PREFIX)as
+AR := $(CX_PREFIX)ar
PY := python3
+STRIP_OSDEP_CC := -ffreestanding -fno-pie
+STRIP_OSDEP_LD := -nostdlib -nolibc -z noexecstack -no-pie -Wl,--build-id=none
-ARCH_OPT := -D__ARCH_IA32
+ARCH_OPT := -m32 -D__ARCH_IA32
O := -O2
W := -Wall -Wextra -Werror -Wno-unknown-pragmas \
-Wno-unused-function \
-fno-inline-small-functions \
-fno-indirect-inlining
-CFLAGS := -std=gnu99 -ffreestanding -MMD $(OFLAGS) $(W) $(ARCH_OPT)
+CFLAGS := $(ARCH_OPT) -std=gnu99 -MMD $(OFLAGS) $(W)
ifeq ($(BUILD_MODE),debug)
O = -Og
CFLAGS += -g
endif
-CFLAGS += $(O)
+CFLAGS += $(O) $(STRIP_OSDEP_CC)
-LDFLAGS := -ffreestanding $(O) -nostdlib -lgcc
+LDFLAGS := $(ARCH_OPT) $(O) $(STRIP_OSDEP_LD)
MKFLAGS := --no-print-directory
\ No newline at end of file
#define __LUNAIX_SYS_LUNAIX_H
#include <lunaix/types.h>
+#include <stddef.h>
void
yield();
#ifndef __LUNAIX_SYS_MANN_H
#define __LUNAIX_SYS_MANN_H
+#include <stddef.h>
#include <lunaix/mann_flags.h>
#include <lunaix/types.h>
#define __LUNAIX_SYS_UNISTD_H
#include <lunaix/types.h>
+#include <stddef.h>
extern const char** environ;
%.S.o: %.S
@$(call status_,AS,$@)
- @$(CC) $(libc_include_opt) $(global_include_opt) -c $< -o $@
+ @$(CC) $(CFLAGS) $(libc_include_opt) $(global_include_opt) -c $< -o $@
$(build_lib)/$(BUILD_NAME): $(obj_files)
@$(call status_,AR,$(*F))
sh_exec(const char* name, const char** argv)
{
if (!strcmp(name, "cd")) {
- chdir(argv[0]);
+ chdir(argv[0] ? argv[0] : ".");
sh_printerr();
return;
}
// stdout (by default, unless user did smth) is the tty we are currently at
ioctl(stdout, TIOCSPGRP, getpgid());
- char* argv[] = { 0, 0 };
+ char* argv[] = {0, 0};
while (1) {
getcwd(pwd, 512);