COSMOS - ubertini

MASSIMO UBERTINI
COSMOS
WWW.UBERTINI.IT
USER KIT
OLIVETTI
SO (Sistema Operativo) sviluppato da Olivetti tra il 1973 e il 1975, implementava il
multitasking real-time, uno dei primi sistemi a farlo.
È stato utilizzato in numerosi computer, tra cui M30, M40, M60 e M70.
COSMOS (C# OPEN SOURCE MANAGED OPERATING SYSTEM)
Sviluppatore:
Famiglia:
Modello del sorgente:
Tipo di kernel:
Licenza:
Sito web:
Cosmos Project.
SO.
Open Source.
Micro Kernel.
BSD (Berkeley Software Distribution).
https://github.com/CosmosOS/Cosmos
È un SO scritto in Visual C#, include il compilatore IL2CPU per convertire il bytecode in
istruzioni native, può essere anche compilato usando Mono.
Cosmos usa il bootloader Syslinux.
Non è tra gli obiettivi di Cosmos essere un SO completo ma piuttosto un set di strumenti per
costruirsi il proprio SO, può anche agire come HAL (Hardware Abstraction Layer).
Cosmos è disponibile in due formati.
1. User Kit: consente di sviluppare il proprio SO personalizzato in Visual Studio.
2. Dev Kit: è il sorgente di Cosmos.
Risorse
 Develop Your Own Operating System in C# or VB.NET
 Quick View Under the Hood
 Intro to Plugs
 X86 Assembly Debugger Preview
 Making a Remote PC Slave for Debugging or Fun
 Cosmos Tutorials
 Cosmos Projects
Video ufficiali
 Building your first Operating System in less than 60 seconds
 Cosmos Debugging
 Cosmos PXE network boot with VMware
 Debugging on real hardware
 User Cosmos videos on YouTube (Cosmos, C#)
Video
 Cosmos Tutorial C# Lesson 1 - Part 1 - int0x10.com
 Cosmos Tutorial C# Lesson 1 - Part 2 - int0x10.com
 Cosmos Tutorial C# Lesson 2 - int0x10.com
Cosmos
um 1 di 25
Visual C#
Il template crea una soluzione con due progetti.
File KERNEL.CS
using System;
using System.Collections.Generic;
using System.Text;
using Sys = Cosmos.System;
namespace CosmosKernel1 {
Cosmos
um 2 di 25
public class Kernel : Sys.Kernel {
protected override void BeforeRun()
{ Console.WriteLine("Cosmos booted successfully. Type a line of text to get it echoed
back."); }
protected override void Run()
{ Console.Write("Input: ");
var input = Console.ReadLine();
Console.Write("Text typed: ");
Console.WriteLine(input);
}
}
}
Selezionare il progetto CosmosKernel1.
Fare clic su Progetto/Proprietà di CosmosKernel1….
Scheda Compila/Piattaforma di destinazione x86.
Selezionare il progetto CosmosKernel1Boot.
Fare clic su Progetto/Proprietà.
Cosmos può fare il boot su H/W reale.
1. USB (Universal Serial Bus).
2. Ethernet.
3. DVD.
4. Disco rigido.
5. Macchina virtuale, per esempio Hyper-V o VMware.
Eseguire l’applicazione, il codice è trasformato in una ISO di SO.
Cosmos
um 3 di 25
Nella cartella seguente, c’è il file ISO.
F:\ESERCIZI\C#\COSMOS\COSMOSKERNEL1\COSMOSKERNEL1\BIN\DEBUG
Fare clic con il pulsante destro, selezionare Monta.
Cosmos
um 4 di 25
HYPER-V
Aprire Console di gestione di Hyper-V e creare la macchina virtuale Cosmos.
Cosmos
um 5 di 25
PROGETTO
File KERNEL.CS
using System;
using System.Collections.Generic;
using System.Text;
using Sys = Cosmos.System;
namespace CosmosKernel1 {
public class Kernel : Sys.Kernel {
protected override void BeforeRun()
{ Console.WriteLine("Cosmos ha fatto il boot con successo!"); }
protected override void Run()
{ int a = 1;
int b = 1;
bool OK = true;
Console.WriteLine(a);
Console.WriteLine(b);
while (OK) {
if ((a + b) > (int.MaxValue / 2))
break;
Console.WriteLine(a + b);
b = a + (a = b);
}
}
}
}
Cosmos
um 6 di 25
Inserire un punto d’interruzione nella riga 11 (int a = 1;).
Cosmos
um 7 di 25
WMWARE
Inserire un punto d’interruzione: int a = 1;.
Cosmos
um 8 di 25
Fare clic sul menu Cosmos.
Cosmos
um 9 di 25
Visual F#
Il template crea una soluzione con due progetti.
File KERNEL.FS
namespace CosmosKernel2
open System
type Kernel() =
inherit Cosmos.System.Kernel()
override u.BeforeRun() = (Console.WriteLine("Cosmos booted successfully. Type a line
of text to get it echoed back.");)
override u.Run() =
Console.Write("Input: ");
let input = Console.ReadLine();
Console.Write("Text typed: ");
Console.WriteLine(input);
Cosmos
um 10 di 25
Visual BASIC
Il template crea una soluzione con due progetti.
File KERNEL.VB
Imports System
Imports System.Collections.Generic
Imports System.Text
Namespace CosmosKernel3
Public Class Kernel
Inherits Cosmos.System.Kernel
Protected Overrides Sub BeforeRun()
Console.WriteLine("Cosmos booted successfully. Type a line of text to get it
echoed back.")
End Sub
Protected Overrides Sub Run()
Console.Write("Input: ")
Console.ReadLine()
Console.Write("Text typed: ")
End Sub
End Class
End Namespace
Cosmos
um 11 di 25
DEV KIT
INTRODUZIONE
È il codice sorgente di Cosmos.
\Build
Contiene i file usati per la compilazione del file ISO e delle macchine virtuali: VirtualPC,
VMware, QEMU, per il supporto del boot da ISO CD, USB, Ethernet (PXE).
La cartella VSIP contiene INSTALL.BAT.
\Docs
Documentazione su Cosmos.
\QA
Contiene gli script.
\Resources
Sono le risorse per il programmatore Cosmos.
\Setup
Contiene gli script e le lingue per compilare il Cosmos User Kit Installer.
La creazione ed esecuzione dell’installer comincia da \BUILD\VSIP\INSTALL.BAT.
\Source e \Source2
Contiene il codice sorgente di Cosmos e le librerie.
Cosmos
um 12 di 25
Fare clic su INSTALL.BAT.
Cosmos
um 13 di 25
Bisogna controllare i prerequisiti di sistema.
Nella cartella C:\USERS\MASSIMO\APPDATA\ROAMING\COSMOS USER KIT sono
installate le cartelle seguenti.
Cosmos
um 14 di 25
Esempio, soluzione Cosmos.VS.Debug.
File MAINWINDOW.XAML
<Window x:Class="Cosmos.VS.Debug.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="474" Width="729" xmlns:my="clrnamespace:Cosmos.VS.Debug" Closing="Window_Closing">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="106*"/>
<ColumnDefinition Width="615*"/>
Cosmos
um 15 di 25
</Grid.ColumnDefinitions>
<ListBox Height="155" HorizontalAlignment="Left" Margin="12,12,0,0"
Name="listBox1" VerticalAlignment="Top" Width="389" Grid.ColumnSpan="2" />
<my:RegistersUC Height="341" HorizontalAlignment="Left" Margin="301,0,0,0"
x:Name="uctlRegisters" VerticalAlignment="Top" Width="300" Grid.Column="1" />
<my:AssemblyUC Height="243" HorizontalAlignment="Left" Margin="12,180,0,0"
x:Name="uctlAsmSource" VerticalAlignment="Top" Width="389" FontFamily="Consolas"
Grid.ColumnSpan="2" />
</Grid>
</Window>
File MAINWINDOW.XAML.CS
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using Cosmos.Compiler.Debug;
namespace Cosmos.VS.Debug {
public partial class MainWindow : Window {
public MainWindow()
{ InitializeComponent();
PipeThread.DataPacketReceived += new Action<byte,
byte[]>(PipeThread_DataPacketReceived);
var xServerThread = new Thread(PipeThread.ThreadStartServer);
xServerThread.Start();
}
void PipeThread_DataPacketReceivedInvoke(byte aCommand, byte[] aData)
{ switch (aCommand) {
case DwMsgType.Noop:
break;
case DwMsgType.Stack:
break;
case DwMsgType.Frame:
break;
case DwMsgType.Registers:
uctlRegisters.Update(aData);
break;
case DwMsgType.Quit:
Close();
break;
case DwMsgType.AssemblySource:
Cosmos
um 16 di 25
uctlAsmSource.Update(aData);
break;
}
}
void PipeThread_DataPacketReceived(byte aCmd, byte[] aMsg)
{ Dispatcher.Invoke(DispatcherPriority.Normal,
(Action)delegate() {
PipeThread_DataPacketReceivedInvoke(aCmd, aMsg);
}
);
}
private void Window_Closing(object sender,
System.ComponentModel.CancelEventArgs e)
{ PipeThread.Stop(); }
}
}
Cosmos
um 17 di 25
Esempio, soluzione Cosmos.Deploy.Pixie.
File MAINWINDOW.XAML
Cosmos
um 18 di 25
<Window x:Class="Cosmos.Deploy.Pixie.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="520" Width="525" Loaded="Window_Loaded"
Icon="/Cosmos.Deploy.Pixie;component/Cosmos.ico" ResizeMode="CanMinimize"
Closing="Window_Closing">
<Grid>
<Label Content="Network Interface:" Height="28" HorizontalAlignment="Left"
Margin="12,12,0,0" Name="label1" VerticalAlignment="Top" />
<Label Content="0.0.0.0" Height="28" HorizontalAlignment="Left" Margin="35,38,0,0"
Name="lablNIC" VerticalAlignment="Top" Width="108" />
<Label Content="File Path:" Height="28" HorizontalAlignment="Left"
Margin="12,64,0,0" Name="label2" VerticalAlignment="Top" />
<Label Content="[Path]" Height="28" Margin="35,89,12,0" Name="lablPath"
VerticalAlignment="Top" />
<ListBox Margin="12,238,12,12" Name="lboxLog" />
<ProgressBar Height="23" Margin="35,199,12,0" Name="progFile"
VerticalAlignment="Top" />
<Label Content="Current Transfer:" Height="28" HorizontalAlignment="Left"
Margin="12,113,0,0" Name="label3" VerticalAlignment="Top" />
<Label Content="[File]" Height="28" Margin="35,140,12,0" Name="lablCurrentFile"
VerticalAlignment="Top" />
<Label Content="[Size]" Height="28" Margin="35,165,12,0" Name="lablCurrentSize"
VerticalAlignment="Top" />
<Label Content="Interface is unavailable. Waiting..." Height="28"
HorizontalAlignment="Left" Margin="137,38,0,0" Name="lablWaiting"
VerticalAlignment="Top" Foreground="Red" Visibility="Visible" />
</Grid>
</Window>
File MAINWINDOW.XAML.CS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Threading;
using System.Windows.Threading;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace Cosmos.Deploy.Pixie {
public partial class MainWindow : Window {
protected byte[] mNicIP = new byte[4];
protected DispatcherTimer mCloseTimer = new DispatcherTimer();
protected DispatcherTimer mOnlineTimer = new DispatcherTimer();
Cosmos
um 19 di 25
protected bool mWarningIssued = false;
public MainWindow()
{ InitializeComponent();
lablWaiting.Visibility = Visibility.Hidden;
mCloseTimer.Interval = TimeSpan.FromSeconds(5);
mCloseTimer.Tick += (object sender, EventArgs e) => {
if (mWarningIssued)
Close();
else {
Log("", "Last transfer request completed. Auto closing in " +
mCloseTimer.Interval.TotalSeconds + " seconds.");
mWarningIssued = true;
}
};
mOnlineTimer.Interval = TimeSpan.FromSeconds(1);
mOnlineTimer.Tick += new EventHandler(mOnlineTimer_Tick);
}
void mOnlineTimer_Tick(object sender, EventArgs e)
{ mOnlineTimer.Stop();
UdpClient xUDP = null;
try {
xUDP = new UdpClient(new IPEndPoint(new IPAddress(mNicIP), 67));
}
catch (SocketException ex) {
if (ex.ErrorCode != 10049)
throw;
if (lablWaiting.Visibility == Visibility.Hidden) {
lablWaiting.Visibility = Visibility.Visible;
Log("NIC", "Interface unavailable. Waiting.");
}
mOnlineTimer.Start();
return;
}
lablWaiting.Visibility = Visibility.Hidden;
Log("NIC", "Interface active.");
xUDP.Close();
Start();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{ Title = App.Title;
if (!Directory.Exists(App.PxePath)) {
MessageBox.Show("Specified path does not exist.", Title);
App.Current.Shutdown(-1);
return;
}
lablNIC.Content = App.IpAddress;
lablPath.Content = App.PxePath;
var xBytes = App.IpAddress.Split(".".ToCharArray());
if (xBytes.Length != 4) {
MessageBox.Show("Invalid IP address specified.", Title);
App.Current.Shutdown(-1);
return;
}
for (int i = 0; i < mNicIP.Length; i++)
Cosmos
um 20 di 25
mNicIP[i] = byte.Parse(xBytes[i]);
ClearFile();
Log("NIC", "Checking for interface.");
mOnlineTimer.Start();
}
void ClearFile()
{ lablCurrentFile.Content = "";
lablCurrentSize.Content = "";
progFile.Value = 0;
}
protected void Log(string aSender, string aText)
{ string xPrefix = aSender == "" ? "" : "[" + aSender + "] ";
lboxLog.SelectedItem = lboxLog.Items.Add(xPrefix + aText);
}
protected Thread mDhcpThread;
protected DHCP mDHCP;
protected Thread mTftpThread;
protected TrivialFTP mTFTP;
protected void Start()
{ Log("DHCP", "Starting");
mDhcpThread = new Thread(delegate() {
mDHCP = new DHCP(mNicIP, Path.Combine(App.PxePath, "pxelinux.0"));
mDHCP.OnLog += delegate(DHCP aSender, string aText) {
Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate() {
Log("DHCP", aText);
});
};
mDHCP.Execute();
});
mDhcpThread.Start();
Log("TFTP", "Starting");
mTftpThread = new Thread(delegate() {
mTFTP = new TrivialFTP(mNicIP, App.PxePath);
mTFTP.OnFileStart += delegate(TrivialFTP aSender, string aFilename, long aSize) {
Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate() {
mCloseTimer.Stop();
Log("TFTP", "Starting file " + aFilename);
lablCurrentFile.Content = aFilename;
double xMB = (double)aSize / (1024 * 1024);
lablCurrentSize.Content = xMB.ToString("0.00") + " MB";
progFile.Value = 0;
progFile.Maximum = aSize;
});
};
mTFTP.OnFileTransfer += delegate(TrivialFTP aSender, string aFilename, long
aPosition) {
Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate() {
progFile.Value = aPosition;
});
};
mTFTP.OnFileCompleted += delegate(TrivialFTP aSender, string aFilename) {
Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate() {
ClearFile();
Log("TFTP", "Completed " + aFilename);
Cosmos
um 21 di 25
mCloseTimer.Start();
});
};
mTFTP.Execute();
});
mTftpThread.Start();
}
private void Window_Closing(object sender,
System.ComponentModel.CancelEventArgs e)
{ if (mDhcpThread != null) {
mDhcpThread.Abort();
mDHCP.Stop();
}
if (mTftpThread != null) {
mTftpThread.Abort();
mTFTP.Stop();
}
}
}
}
Cosmos
um 22 di 25
Esempio, soluzione Cosmos.System.
File ICMPPACKET.CS
using System;
using Sys = System;
namespace Cosmos.System.Network.IPv4 {
internal class ICMPPacket : IPPacket {
protected byte icmpType;
protected byte icmpCode;
protected UInt16 icmpCRC;
File IPPACKET.CS
using System;
using System.Collections.Generic;
using System.Linq;
Cosmos
um 23 di 25
using System.Text;
using Cosmos.HAL.Network;
using Cosmos.System.Network.ARP;
namespace Cosmos.System.Network.IPv4 {
public class IPPacket : EthernetPacket {
protected byte ipVersion;
protected byte ipHeaderLength;
protected byte tos;
protected UInt16 ipLength;
protected UInt16 fragmentID;
protected UInt16 fragmentOffset;
protected byte flags;
protected byte ttl;
protected byte proto;
protected UInt16 ipCRC;
protected Address sourceIP;
protected Address destIP;
protected UInt16 dataOffset;
private static UInt16 sNextFragmentID;
File UDPPACKET.CS
using System;
using Sys = System;
namespace Cosmos.System.Network.IPv4 {
public class UDPPacket : IPPacket {
protected UInt16 sourcePort;
protected UInt16 destPort;
protected UInt16 udpLen;
protected UInt16 udpCRC;
File ETHERNETPACKET.CS
using System;
using Cosmos.HAL.Network;
namespace Cosmos.System.Network {
public class EthernetPacket {
protected byte[] mRawData;
protected MACAddress srcMAC;
protected MACAddress destMAC;
protected UInt16 aEtherType;
File NETWORKSTACK.CS
using System;
using Sys = System;
using System.Collections.Generic;
using Cosmos.HAL;
using Cosmos.System.Network.ARP;
namespace Cosmos.System.Network {
public static class NetworkStack {
internal static TempDictionary<NetworkDevice> AddressMap
{ get; private set; }
public static void Init()
Cosmos
um 24 di 25
{ AddressMap = new TempDictionary<NetworkDevice>();
Cosmos.System.Network.ARP.ARPPacket.VMTInclude();
Cosmos.System.Network.IPv4.ARPReply_Ethernet.VMTInclude();
Cosmos.System.Network.IPv4.ARPRequest_Ethernet.VMTInclude();
Cosmos.System.Network.IPv4.ICMPPacket.VMTInclude();
Cosmos.System.Network.IPv4.ICMPEchoReply.VMTInclude();
Cosmos.System.Network.IPv4.ICMPEchoRequest.VMTInclude();
Cosmos.System.Network.IPv4.UDPPacket.VMTInclude();
}
public static void ConfigIP(NetworkDevice nic, IPv4.Config config)
{ AddressMap.Add(config.IPAddress.Hash, nic);
IPv4.Config.Add(config);
nic.DataReceived = HandlePacket;
}
internal static void HandlePacket(byte[] packetData)
{ Sys.Console.Write("Received Packet Length=");
if (packetData == null) {
Sys.Console.WriteLine("**NULL**");
return;
}
Sys.Console.WriteLine(packetData.Length);
UInt16 etherType = (UInt16)((packetData[12] << 8) | packetData[13]);
switch (etherType) {
case 0x0806:
ARPPacket.ARPHandler(packetData);
break;
case 0x0800:
IPv4.IPPacket.IPv4Handler(packetData);
break;
}
}
public static void Update()
{ IPv4.OutgoingBuffer.Send(); }
}
}
Cosmos
um 25 di 25
UBERTINI MASSIMO
http://www.ubertini.it
[email protected]
Dip. Informatica Industriale
I.T.I.S. "Giacomo Fauser"
Via Ricci, 14
28100 Novara Italy
tel. +39 0321482411
fax +39 0321482444
http://www.fauser.edu
[email protected]