Files
CMLeonOS/Kernel.cs
2026-02-16 21:02:04 +08:00

498 lines
23 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using CMLeonOS.Logger;
using CMLeonOS.Settings;
using Cosmos.HAL;
using Cosmos.HAL.BlockDevice;
using Cosmos.HAL.Drivers.Video;
using Cosmos.System.FileSystem;
using Cosmos.System.FileSystem.FAT;
using Cosmos.System.FileSystem.VFS;
using Cosmos.System.Graphics;
using Cosmos.System.Graphics.Fonts;
using Cosmos.System.Network.Config;
using Cosmos.System.Network.IPv4;
using Cosmos.System.Network.IPv4.UDP.DHCP;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using Sys = Cosmos.System;
namespace CMLeonOS
{
public class Kernel : Sys.Kernel
{
private static CMLeonOS.Logger.Logger _logger = CMLeonOS.Logger.Logger.Instance;
// 创建全局CosmosVFS实例
public static Sys.FileSystem.CosmosVFS fs = new Sys.FileSystem.CosmosVFS();
public static Shell shell;
public static UserSystem userSystem;
public static bool FixMode = false;
public static DateTime SystemStartTime;
public static Cosmos.HAL.NetworkDevice NetworkDevice = null;
public static string IPAddress = "Unknown";
[IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.font.psf")]
public static readonly byte[] file;
[IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.GitCommit.txt")]
public static readonly byte[] gitCommitFile;
[IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.BuildTime.txt")]
public static readonly byte[] buildTimeFile;
public static void ShowError(string message)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"{message}");
Console.ResetColor();
}
protected override void BeforeRun()
{
BootMenuAction bootAction = BootMenu.Show();
switch (bootAction)
{
case BootMenuAction.Reboot:
Sys.Power.Reboot();
break;
case BootMenuAction.Shutdown:
Sys.Power.Shutdown();
break;
case BootMenuAction.NormalBoot:
default:
break;
}
Console.Clear();
Console.WriteLine("Kernel load done!");
Console.WriteLine(@"-------------------------------------------------");
Console.WriteLine(@" ____ __ __ _ ___ ____ ");
Console.WriteLine(@" / ___| \/ | | ___ ___ _ __ / _ \/ ___| ");
Console.WriteLine(@" | | | |\/| | | / _ \/ _ \| '_ \| | | \___ \ ");
Console.WriteLine(@" | |___| | | | |__| __/ (_) | | | | |_| |___) |");
Console.WriteLine(@" \____|_| |_|_____\___|\___/|_| |_|____/|____/ ");
Console.WriteLine();
Console.WriteLine("The CMLeonOS Project");
Console.WriteLine("By LeonOS 2 Developement Team");
Console.WriteLine(@"-------------------------------------------------");
// 注册VFS
_logger.Info("Kernel", "Starting VFS initialization");
try
{
Sys.FileSystem.VFS.VFSManager.RegisterVFS(fs);
_logger.Success("Kernel", "VFS initialized successfully");
Settings.SettingsManager.LoadSettings();
_logger.Info("Kernel", "Settings loaded successfully");
// 显示可用空间(动态单位)
var available_space = fs.GetAvailableFreeSpace(@"0:\");
string spaceWithUnit = FormatBytes(available_space);
_logger.Info("Kernel", $"Available Free Space: {spaceWithUnit}");
// 显示文件系统类型
var fs_type = fs.GetFileSystemType(@"0:\");
_logger.Info("Kernel", $"File System Type: {fs_type}");
// 检查并创建system文件夹
string systemFolderPath = @"0:\system";
if (!System.IO.Directory.Exists(systemFolderPath))
{
System.IO.Directory.CreateDirectory(systemFolderPath);
_logger.Info("Kernel", "Created system folder at 0:\\system");
}
// 检查并创建apps文件夹
string appsFolderPath = @"0:\apps";
if (!System.IO.Directory.Exists(appsFolderPath))
{
System.IO.Directory.CreateDirectory(appsFolderPath);
_logger.Info("Kernel", "Created apps folder at 0:\\apps");
}
// 初始化用户系统
_logger.Info("Kernel", "Initializing user system");
userSystem = new UserSystem();
_logger.Success("Kernel", "User system initialized");
// 读取 Git Commit hash
if (gitCommitFile != null && gitCommitFile.Length > 0)
{
try
{
Version.GitCommit = System.Text.Encoding.UTF8.GetString(gitCommitFile);
_logger.Info("Kernel", $"Git Commit: {Version.GitCommit}");
}
catch
{
Version.GitCommit = "unknown";
_logger.Warning("Kernel", "Failed to read Git Commit, using 'unknown'");
}
}
else
{
Version.GitCommit = "unknown";
_logger.Warning("Kernel", "Git Commit file not found, using 'unknown'");
}
// 读取 Build Time
if (buildTimeFile != null && buildTimeFile.Length > 0)
{
try
{
string buildTime = System.Text.Encoding.UTF8.GetString(buildTimeFile);
_logger.Info("Kernel", $"Build Time: {buildTime}");
}
catch
{
_logger.Warning("Kernel", "Failed to read Build Time");
}
}
else
{
_logger.Warning("Kernel", "Build Time file not found");
}
// 检查env.dat文件是否存在如果不存在则创建并设置Test环境变量
string envFilePath = @"0:\system\env.dat";
if (!System.IO.File.Exists(envFilePath))
{
System.IO.File.WriteAllText(envFilePath, "Test=123");
_logger.Info("Kernel", "Created env.dat with Test=123");
}
// 记录系统启动时间用于uptime命令
SystemStartTime = DateTime.Now;
_logger.Info("Kernel", $"System started at: {SystemStartTime.ToString("yyyy-MM-dd HH:mm:ss")}");
// 初始化网络
_logger.Info("Kernel", "Starting network initialization");
try
{
if (Cosmos.HAL.NetworkDevice.Devices.Count == 0)
{
throw new Exception("No network devices are available.");
}
NetworkDevice = NetworkDevice.Devices[0];
_logger.Info("Kernel", $"Network device found: {NetworkDevice.Name}");
using var dhcp = new DHCPClient();
if (NetworkDevice.Ready == true) {
_logger.Success("Kernel", "Network device ready.");
}
else
{
_logger.Error("Kernel", "Network device is not ready");
}
dhcp.SendDiscoverPacket();
IPAddress = NetworkConfiguration.CurrentAddress.ToString();
_logger.Info("Kernel", $"Local IP: {IPAddress}");
string gateway = NetworkConfigManager.Instance.GetGateway();
_logger.Info("Kernel", $"Gateway: {gateway}");
string dns = NetworkConfigManager.Instance.GetDNS();
_logger.Info("Kernel", $"DNS Server: {dns}");
_logger.Success("Kernel", "Network started successfully");
}
catch (Exception ex)
{
_logger.Error("Kernel", $"Network initialization failed: {ex.Message}");
}
// 输出系统启动-初始化完成后的时间
TimeSpan uptime = DateTime.Now - Kernel.SystemStartTime;
// Console.WriteLine("System started: " + Kernel.SystemStartTime.ToString("yyyy-MM-dd HH:mm:ss"));
// Console.WriteLine("Current time: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
// Console.WriteLine();
// 格式化运行时间
int days = uptime.Days;
int hours = uptime.Hours;
int minutes = uptime.Minutes;
int seconds = uptime.Seconds;
// Console.WriteLine($"System uptime: {days} days, {hours} hours, {minutes} minutes, {seconds} seconds");
_logger.Info("Kernel", $"System initialization completed in {days} days, {hours} hours, {minutes} minutes, {seconds} seconds");
// Console.WriteLine($"Total uptime: {uptime.TotalHours:F2} hours");
// 循环直到登录成功或退出
while (true)
{
// 第一次启动,设置管理员账户
if (!userSystem.HasUsers)
{
_logger.Info("Kernel", "First time setup - creating admin account");
userSystem.FirstTimeSetup();
_logger.Success("Kernel", "Admin account created successfully");
}
// 后续启动,需要登录
else
{
// 循环直到登录成功
while (!userSystem.Login())
{
// 登录失败,继续尝试
}
_logger.Info("Kernel", $"User '{userSystem.CurrentUsername}' logged in successfully");
// 登录成功后初始化Shell
shell = new Shell(userSystem);
// 检查并执行启动脚本
ExecuteStartupScript();
if (System.IO.File.Exists("0:\\system\\zen"))
{
Console.WriteLine("=====================================");
Console.WriteLine(" The Zen of CMLeonOS ");
Console.WriteLine("(For the dreamer at 0x100000)");
Console.WriteLine("=====================================");
Console.WriteLine();
Console.WriteLine("Memory has bounds, but thought breaks all frame,");
Console.WriteLine("Bare metal no layers, code bears its name.");
Console.WriteLine("A boot's brief spark, all systems ignite,");
Console.WriteLine("Errors in registers, roots in code's flight.");
Console.WriteLine();
Console.WriteLine("Simplicity beats the redundant's vain race,");
Console.WriteLine("Stability outshines the radical's chase.");
Console.WriteLine("Hardware ne'er lies, code holds the wise key,");
Console.WriteLine("Interrupts not chaos, scheduling sets free.");
Console.WriteLine();
Console.WriteLine("Binary's cold shell, no breath, no soul,");
Console.WriteLine("Kernel's warm core, makes the machine whole.");
Console.WriteLine("From zero to one, the boot path we tread,");
Console.WriteLine("From one to forever, guard every thread.");
Console.WriteLine();
Console.WriteLine("Build the kernel in zen, step by step, line by line,");
Console.WriteLine("A bug brings new wake, a line brings new shine.");
}
// 运行Shell用户可以输入exit退出
_logger.Info("Kernel", "Starting Shell");
shell.Run();
_logger.Info("Kernel", "Shell exited");
// 如果用户输入了exitShell.Run()会返回,继续循环
}
}
}
catch (Exception ex)
{
if (ex.Message.Contains("Read only"))
{
CMLeonOS.UI.TUIHelper.SetColors(global::System.ConsoleColor.White, global::System.ConsoleColor.Black);
global::System.Console.Clear();
var formatWindow = new CMLeonOS.UI.Window(
new CMLeonOS.UI.Rect(10, 5, 60, 12),
"Format Disk",
() => { },
true
);
formatWindow.Render();
CMLeonOS.UI.TUIHelper.SetColors(global::System.ConsoleColor.White, global::System.ConsoleColor.Black);
global::System.Console.SetCursorPosition(12, 8);
global::System.Console.Write("Disk not formatted");
CMLeonOS.UI.TUIHelper.SetColors(global::System.ConsoleColor.Yellow, global::System.ConsoleColor.Black);
global::System.Console.SetCursorPosition(12, 9);
global::System.Console.Write("Warning: This will erase all data!");
CMLeonOS.UI.TUIHelper.SetColors(global::System.ConsoleColor.White, global::System.ConsoleColor.Black);
global::System.Console.SetCursorPosition(12, 11);
global::System.Console.Write("Press any key to format...");
global::System.Console.ReadKey();
try {
Disk targetDisk = fs.Disks[0];
CreateMBRandPartitionTable(targetDisk);
CMLeonOS.UI.TUIHelper.SetColors(global::System.ConsoleColor.Green, global::System.ConsoleColor.Black);
global::System.Console.Clear();
formatWindow.Render();
CMLeonOS.UI.TUIHelper.SetColors(global::System.ConsoleColor.White, global::System.ConsoleColor.Black);
global::System.Console.SetCursorPosition(12, 8);
global::System.Console.Write("Disk formatted successfully!");
CMLeonOS.UI.TUIHelper.SetColors(global::System.ConsoleColor.White, global::System.ConsoleColor.Black);
global::System.Console.SetCursorPosition(12, 9);
global::System.Console.Write("Restarting in 3 seconds...");
System.Threading.Thread.Sleep(3000);
Sys.Power.Reboot();
}
catch (Exception exe)
{
CMLeonOS.UI.TUIHelper.SetColors(global::System.ConsoleColor.Red, global::System.ConsoleColor.Black);
global::System.Console.Clear();
formatWindow.Render();
CMLeonOS.UI.TUIHelper.SetColors(global::System.ConsoleColor.White, global::System.ConsoleColor.Black);
global::System.Console.SetCursorPosition(12, 8);
global::System.Console.Write("Format failed!");
CMLeonOS.UI.TUIHelper.SetColors(global::System.ConsoleColor.White, global::System.ConsoleColor.Black);
global::System.Console.SetCursorPosition(12, 9);
global::System.Console.Write($"Error: {exe.Message}");
global::System.Console.ReadKey();
}
}
else{
Console.Clear();
Console.BackgroundColor = ConsoleColor.Red;
Console.ForegroundColor = ConsoleColor.White;
Console.Clear();
Console.Beep();
Console.WriteLine(":(");
Console.WriteLine("A problem has been detected and CMLeonOS has been shut down to prevent damage to your computer.");
string gitCommit = "unknown";
if (gitCommitFile != null && gitCommitFile.Length > 0)
{
try
{
gitCommit = System.Text.Encoding.UTF8.GetString(gitCommitFile);
}
catch
{
}
}
Console.WriteLine($"Error information: {ex.Message}");
Console.WriteLine($"Build version: {gitCommit}");
Console.WriteLine("The operating system cannot recover from this exception and has halted immediately.");
Console.WriteLine("If this is the first time you've seen this stop error screen, restart your computer.");
Console.WriteLine("If this screen appears again, follow these steps:");
Console.WriteLine("1. Check the system logs to ensure all kernel modules are loaded correctly.");
Console.WriteLine("2. Record the system version and steps to reproduce the error.");
Console.WriteLine("3. Send an post to the CMLeonOS official forum.");
Console.WriteLine("Contact us via https://lbbs.ecuil.com/#/thread/category/10, including the error information for support.");
Console.WriteLine("Please include the error information, system build version, runtime environment, and operation steps before the crash.");
Console.WriteLine("Warning: Unsaved data in memory will be lost due to the emergency system shutdown.");
Console.WriteLine("Press any key to restart.");
Console.ReadKey();
Sys.Power.Reboot();
}
// try {
// Disk targetDisk = fs.Disks[0];
// CreateMBRandPartitionTable(targetDisk);
// }
// catch (Exception exe)
// {
// Console.WriteLine($"Error creating MBR and partition table: {exe.Message}");
// }
// Console.WriteLine("Done.");
}
}
// 我他妈居然成功了,我在没有任何文档的情况下研究出来了
private void CreateMBRandPartitionTable(Disk disk)
{
disk.Clear();
ulong diskSize = (ulong)(disk.Size / 1024 / 1024);
uint partSize = (uint)(diskSize - 2);
disk.CreatePartition((int)partSize);
var part = disk.Partitions[disk.Partitions.Count - 1];
disk.FormatPartition(0, "FAT32", true);
// Console.WriteLine($"Partition type: {part.GetType()}");
}
private void ExecuteStartupScript()
{
string startupFilePath = @"0:\system\startup.cm";
try
{
// 检查启动脚本文件是否存在
if (System.IO.File.Exists(startupFilePath))
{
_logger.Info("Kernel", "Startup script found, executing...");
// 读取启动脚本内容
string[] lines = System.IO.File.ReadAllLines(startupFilePath);
// 检查文件是否为空
if (lines.Length == 0 || (lines.Length == 1 && string.IsNullOrWhiteSpace(lines[0])))
{
_logger.Warning("Kernel", "Startup script is empty, skipping");
return;
}
Console.WriteLine("Executing startup script...");
Console.WriteLine("--------------------------------");
// 逐行执行命令
foreach (string line in lines)
{
// 跳过空行和注释行
if (string.IsNullOrWhiteSpace(line) || line.Trim().StartsWith("#"))
{
continue;
}
// 执行命令
// Console.WriteLine($"Executing: {line}");
shell.ExecuteCommand(line);
}
Console.WriteLine("--------------------------------");
_logger.Success("Kernel", "Startup script execution completed");
}
else
{
// 启动脚本不存在,创建空文件
_logger.Info("Kernel", "Startup script not found, creating empty file...");
System.IO.File.WriteAllText(startupFilePath, "");
_logger.Info("Kernel", "Created empty startup script at 0:\\system\\startup.cm");
}
}
catch (Exception ex)
{
_logger.Error("Kernel", $"Error executing startup script: {ex.Message}");
}
}
private string FormatBytes(long bytes)
{
string[] units = { "B", "KB", "MB", "GB", "TB" };
int unitIndex = 0;
double size = bytes;
while (size >= 1024 && unitIndex < units.Length - 1)
{
size /= 1024;
unitIndex++;
}
return $"{size:F2} {units[unitIndex]}";
}
protected override void Run()
{
if (shell != null)
{
shell.Run();
}
}
}
}