<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: YT</title>
    <description>The latest articles on DEV Community by YT (@ytannai).</description>
    <link>https://dev.to/ytannai</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F658541%2F49309322-81e7-4d4f-860c-0493df5cb4a0.png</url>
      <title>DEV Community: YT</title>
      <link>https://dev.to/ytannai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ytannai"/>
    <language>en</language>
    <item>
      <title>形式手法の話</title>
      <dc:creator>YT</dc:creator>
      <pubDate>Fri, 30 Jul 2021 15:46:14 +0000</pubDate>
      <link>https://dev.to/ytannai/-42m6</link>
      <guid>https://dev.to/ytannai/-42m6</guid>
      <description>&lt;h1&gt;
  
  
  背景
&lt;/h1&gt;

&lt;p&gt;社内で形式手法の勉強会が行われた。この&lt;a href="https://www.marulabo.net/docs/aws-formal/"&gt;リンク&lt;/a&gt;の内容。全3回のうちの第1回らしい。&lt;br&gt;
形式手法は知ってはいたけど、非常にコストが高く実務的ではないという認識だった。この勉強会は、クラウドなど産業界で実際に使われている事例を紹介して、興味を持つことを目指しているようだった。&lt;/p&gt;

&lt;p&gt;勉強会のスライドを読み進めると、上記リンク中の参考資料1「&lt;a href="https://drive.google.com/file/d/1OY7GmEZLTDnIgS3D0JlsLFOz7qmWGeRv/view"&gt;Amazon Web Services はどのように形式手法を利用したか&lt;/a&gt;」を読むよう記載されており、読んでみると非常に興味深いものだった。&lt;br&gt;
勉強会第一回の内容と合わせて、面白いと思ったところをまとめてみる。&lt;/p&gt;

&lt;h1&gt;
  
  
  AWSでの形式手法の利用
&lt;/h1&gt;

&lt;p&gt;報道されるような重要なシステムでの大規模障害の原因は様々で、対処方法も複数ある。&lt;br&gt;
仕様の誤りに形式手法で対応できれば、正確な仕様を元にした実装とテストができ、障害を防ぐことができる。&lt;br&gt;
障害発生後の原因は調査しやすいが、障害発生前に防ぐことは難しい。形式手法ならそれができる。&lt;br&gt;
クラウドのような大規模かつ複雑な並列・分散システムでは、ハードウェアや人間のエラーも想定しなければならない。このような複雑な仕様を、検証可能で表現力のある形式手法で取り扱うことが必要となっている。&lt;/p&gt;

&lt;p&gt;形式手法で検証可能な仕様が記載されれば、そこから実装を生成することもできるかもしれない。その場合、実装する人間は仕事が少なくなるかもしれない。&lt;br&gt;
しかし、仕様を作成する仕事は創造性が求められ、これは人間にしかできない。&lt;/p&gt;

&lt;h1&gt;
  
  
  Amazon Web Services はどのように形式手法を利用したか
&lt;/h1&gt;

&lt;p&gt;形式手法ではない、業界で一般的な方法では、大規模分散システムのレアケースを未然に発見することはできなかった。&lt;br&gt;
この問題を解決することを目標として、代替手段を探し始めた。&lt;/p&gt;

&lt;p&gt;複雑な仕様を厳密に記述しつつ、記述量を抑制するソリューションとして、&lt;a href="https://lamport.azurewebsites.net/tla/tla.html"&gt;TLA+&lt;/a&gt;を見出した。&lt;br&gt;
TLA+は離散数学に基づいた形式的仕様記述言語で、モデルチェッカーはもちろん、疑似コードを置き換える表現力を持つPlusCal言語を備えている。&lt;/p&gt;

&lt;p&gt;設計にTLA+を使うことの副次的な利点として、人間の設計手法を向上させることがある。&lt;br&gt;
TLAによらない既存の手法では、まずビジネス要求に応える最短のハッピーケースを設計し、その後でエンジニア個人の知識と経験に基づき問題点の検討を行う。この場合、能力を超える複雑な問題を見つけることはできない。&lt;br&gt;
TLA+の場合はまず「正しく進むには何が必要か」というシステム特性を、安全性と生存性の観点から記述することから始まる。次に、ハードウェアの異常や人間のミスなど、起こりうる動的イベントを特定する。その後、モデルチェッカーで仕様の正しさを確認する。&lt;br&gt;
前者は「うまくいかないもの」をアドホックに見つけ、後者は「正しく進むために必要なもの」を厳密に特定する。&lt;/p&gt;

&lt;p&gt;形式手法はまた、仕様が安全であること、または安全ではないことを、事前に知ることができる。&lt;br&gt;
さらに、優れたドキュメントとして機能する。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;さらに、設計の正確でテスト可能な、十分にコメントされた記述は、優れた形式のドキュメントである。というのも、AWS システムのライフタイムには期限がないため、このことは、重要である。&lt;br&gt;
時間が経過し、ビジネスの成⻑とともにチームも成⻑する。そのため、我々は定期的に新しい人々をシステムに慣れさせる必要がある。この教育は効果的でなければならない。微妙なバグを作らないようにするには、すべてのエンジニアがシステムの同じメンタルモデルを持つことが必要なのだが、その共有モデルは、精密で正確で完全である必要がある。&lt;br&gt;
エンジニアはさまざまな方法でメンタルモデルを形成する。互いに話し合ったり、設計ドキュメントを読んだり、コードを読んだり、バグ修正や小さな機能を実装したりする。 しかし、会話や設計のドキュメントはあいまいであったり不完全であったりする。実行可能コードが大きすぎてすぐに理解できなかったり、あるいはそのコードは意図したデザインを正確に反映していない場合があるのだ。 対照的に、形式仕様は、正確で短く、ツールを使用して調査や実験ができる。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;TLA+に向いていないこともある。AWSのインフラはハード・リアルタイムスケジューリングをサポートしておらず、サービスに対しては一定以上の遅延をエラーとみなすソフト・リアルタイムスケジューリングが要求されている。&lt;br&gt;
TLA+では安全上の特性として応答時間の上限を設定できるが、このギャップを埋めるには至っていない。&lt;/p&gt;

&lt;h2&gt;
  
  
  AWSでの形式手法の導入経緯
&lt;/h2&gt;

&lt;p&gt;バグを防ぐ手法を模索する上で、形式手法はROIが低いという偏見があり、当初は検討されていなかった。&lt;br&gt;
ある時、形式手法言語&lt;a href="http://alloytools.org/"&gt;Alloy&lt;/a&gt;によって分散システムのメンバーシップ・プロトコル&lt;a href="https://ja.wikipedia.org/wiki/Chord"&gt;Chord&lt;/a&gt;の不具合を見つけたことで、有用性を認識した。&lt;br&gt;
Allowの表現力不足を解決する方法を模索していた際、LamportのFast Paxos論文のAppendixにTLA+仕様が記載されていることを見つけた。&lt;br&gt;
Paxosアルゴリズム作成者がTLA+を作ったという事実は、TLA+の実用性を確信させるものだった。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://link.springer.com/article/10.1007%2Fs00446-006-0005-x"&gt;Lamport, L. Fast Paxos. Distrib. Comput. 19, 79–103 (2006). https://doi.org/10.1007/s00446-006-0005-x&lt;/a&gt;&lt;br&gt;
※自分は論文へのアクセス権を持っていないので未確認&lt;/p&gt;

&lt;p&gt;発見者はAmazonの同僚にTLA+を薦めたが、必要性がなく導入はされなかった。&lt;br&gt;
しかしDynamoDBで採用され、TLA＋の学習と仕様記述を2週間で行い、8Coreと23GBのEC2インスタンス10台でモデルチェッカーの分散バージョンを実行して、データが失われるバグを発見した。&lt;br&gt;
このDynamoDBでの成功と、社内へのプレゼンテーションの工夫によって、TLA+を伝える試みを改善させた。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;エンジニアは「検証」ではなくデバッグの観点から考えるため、プレゼンテーションでは「設計のデバッグ」と呼んだ[18]。こうしたメタファーを続けながら、エンジニアは、「徹底的にテスト可能な疑似コード」と呼ぶと、TLA+の概念と実用的な価値をより簡単に把握できることに気づいた。 形式手法は実践的ではないと広く見られていたため、最初は「形式」、「検証」、「証明」という言葉を使うのを避けた。また、我々は、最初に TLA が何を表すのかについて言及することは避けた。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;このような活動によって、S3のチームから導入サポートの依頼があった。&lt;/p&gt;

&lt;p&gt;結果として、2011年から現在に至るまで、AWSでは形式手法が用いられている。&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Rustで自作OS 6日目</title>
      <dc:creator>YT</dc:creator>
      <pubDate>Sun, 11 Jul 2021 09:15:01 +0000</pubDate>
      <link>https://dev.to/ytannai/rust-os-6-l40</link>
      <guid>https://dev.to/ytannai/rust-os-6-l40</guid>
      <description>&lt;p&gt;引き続き第3章 boot loaderを進める。&lt;br&gt;
&lt;a href="https://os.phil-opp.com/ja/minimal-rust-kernel/#kaneruwoshi-xing-suru" rel="noopener noreferrer"&gt;https://os.phil-opp.com/ja/minimal-rust-kernel/#kaneruwoshi-xing-suru&lt;/a&gt;&lt;br&gt;
&lt;a href="https://crates.io/crates/bootloader" rel="noopener noreferrer"&gt;bootloader&lt;/a&gt; crateというものがあるらしいけど、まずは自作を試みる。&lt;br&gt;
でも参考にはする。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;私達のカーネルをELFファイルにコンパイルする。&lt;br&gt;
依存であるbootloaderをスタンドアロンの実行ファイルとしてコンパイルする。&lt;br&gt;
カーネルのELFファイルのバイト列をブートローダーにリンクする。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;たぶんリンクはlld、それ以外はcargo(rustc)で進める。&lt;/p&gt;

&lt;p&gt;まずはELF形式のカーネルをビルドする。&lt;br&gt;
ビルド設定を&lt;code&gt;target.json&lt;/code&gt;として作成する。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"llvm-target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"x86_64-unknown-none"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data-layout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e-m:e-i64:64-f80:128-n8:16:32:64-S128"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"arch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"x86_64"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"target-endian"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"little"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"target-pointer-width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"64"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"target-c-int-width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"32"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"os"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"none"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"executables"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"linker-flavor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ld.lld"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"linker"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rust-lld"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"panic-strategy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"abort"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"disable-redzone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"features"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-mmx,-sse,+soft-float"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exe-suffix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".elf"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;コマンド &lt;code&gt;build --target target.json --package kernel --bin kernel&lt;/code&gt; でビルドできる。&lt;br&gt;
macOSの場合、binutilsの&lt;code&gt;greadelf&lt;/code&gt;でバイナリを確認できる。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ brew install binutils
$ /usr/local/Cellar/binutils/2.36.1/bin/greadelf -h ../target/target/debug/kernel.elf
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x201120
  Start of program headers:          64 (bytes into file)
  Start of section headers:          4472 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         4
  Size of section headers:           64 (bytes)
  Number of section headers:         15
  Section header string table index: 13
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Entry point addressが自作OS本とは合っていないが、とりあえずboot loaderにカーネルを読み込む処理を実装する。&lt;/p&gt;

&lt;p&gt;調べてたら先駆者を見つけた。&lt;br&gt;
&lt;a href="https://natsutan.hatenablog.com/entry/2021/04/14/190451" rel="noopener noreferrer"&gt;https://natsutan.hatenablog.com/entry/2021/04/14/190451&lt;/a&gt;&lt;br&gt;
この人はCのUEFIアプリからRustのカーネルを読んでいるようだけど、自分は全部Rustでやってみたい。&lt;/p&gt;

&lt;p&gt;上記ブログの参考ブログは全部Rustでやってた。&lt;br&gt;
&lt;a href="https://www.akiradeveloper.com/post/mikanos-rust/" rel="noopener noreferrer"&gt;https://www.akiradeveloper.com/post/mikanos-rust/&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;このカーネルファイルは、0x100000に配置されるようにビルドされているため、 UEFIによってアドレス指定方式でページをアロケートして、そこに書きます。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;これが全てっぽい。&lt;/p&gt;

&lt;p&gt;自作OS本と &lt;a href="https://github.com/akiradeveloper/MikanOS.rs/blob/master/boot/src/main.rs" rel="noopener noreferrer"&gt;https://github.com/akiradeveloper/MikanOS.rs/blob/master/boot/src/main.rs&lt;/a&gt; を見ながら進める。&lt;/p&gt;

&lt;p&gt;一通り書いた時点で起動してみると、QEMUがpanicした。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbkpjz1rq10tdcbbaroqx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbkpjz1rq10tdcbbaroqx.png" alt="Screen_Shot_2021-07-11_at_17_48_28"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;ディレクトリ構成を修正すると、panicせず起動できたようだ。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe2hao4jhe9j7x0rjt5hv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe2hao4jhe9j7x0rjt5hv.png" alt="Screen Shot 2021-07-11 at 18.13.06"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2vhxfy00hnhcgfc5pugn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2vhxfy00hnhcgfc5pugn.png" alt="Screen Shot 2021-07-11 at 18.12.46"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;今日の進捗 -&amp;gt; &lt;a href="https://github.com/ytannai/kabos/tree/8e5091cbb471ca660dab44091051d79d692692c2" rel="noopener noreferrer"&gt;https://github.com/ytannai/kabos/tree/8e5091cbb471ca660dab44091051d79d692692c2&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
    </item>
    <item>
      <title>Rustで自作OS 5日目</title>
      <dc:creator>YT</dc:creator>
      <pubDate>Tue, 06 Jul 2021 14:40:48 +0000</pubDate>
      <link>https://dev.to/ytannai/rust-os-5-3pc1</link>
      <guid>https://dev.to/ytannai/rust-os-5-3pc1</guid>
      <description>&lt;p&gt;昨日に引き続き第3章 boot loader。なんとか今日こそ起動したい。&lt;br&gt;
昨日見たブログの次の章を読んでいく。&lt;br&gt;
&lt;a href="https://os.phil-opp.com/ja/minimal-rust-kernel/"&gt;https://os.phil-opp.com/ja/minimal-rust-kernel/&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;しかしながら、私達のターゲットシステムには、いくつか特殊な設定パラメータが必要になります（例えば、その下ではOSが走っていない、など）。なので、既存のtarget tripleはどれも当てはまりません。ありがたいことに、RustではJSONファイルを使って独自のターゲットを定義できます。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;サンプルにあったJSONはカスタムターゲットの設定ファイルだった。どうりでtarget tripleに無いはずだ。&lt;br&gt;
kernelにも同じJSONを配置して試してみる。&lt;/p&gt;

&lt;p&gt;そもそもELFの知識が足りな気がするので、ブログと自作OS本を読み進める。&lt;/p&gt;

&lt;p&gt;カスタムターゲットの指定方法がわからなかったんだけど、&lt;code&gt;--target&lt;/code&gt;オプションに規定のtarget tripleではなく、JSONファイル名（おそらくパス）を設定すれば良いらしい。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cargo build --target x86_64-none-elf.json --package kernel --bin kernel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;あんまり関係ないけど、SIMDのデメリットが載ってて参考になった。Apache ArrowとかSIMDちょっと興味あったので。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;しかし、大きなSIMDレジスタをOSカーネルで使うことは性能上の問題に繋がります。 その理由は、カーネルは、割り込まれたプログラムを再開する前に、すべてのレジスタを元に戻さないといけないためです。これは、カーネルがSIMDの状態のすべてを、システムコールやハードウェア割り込みがあるたびにメインメモリに保存しないといけないということを意味します。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;話はkernelに戻って、やっとcore見つからないエラーが出たので、ブログの通りbuild-std設定を入れて進める。&lt;/p&gt;

&lt;p&gt;ブログだとUEFIについて描いてないし、ELFじゃないので、ここを自作OS本と合わせる必要がありそう。&lt;/p&gt;

</description>
      <category>rust</category>
    </item>
    <item>
      <title>Rustで自作OS 4日目</title>
      <dc:creator>YT</dc:creator>
      <pubDate>Mon, 05 Jul 2021 14:48:02 +0000</pubDate>
      <link>https://dev.to/ytannai/rust-os-4-1od9</link>
      <guid>https://dev.to/ytannai/rust-os-4-1od9</guid>
      <description>&lt;p&gt;第3章 boot loaderをやっていく。まずはデバッグで使うQEMU Monitorの有効化。起動時のオプションに&lt;code&gt;-monitor stdio&lt;/code&gt;をつければ、プロンプトが返ってきて操作ができる。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;QEMU 5.2.0 monitor - type 'help' for more information
(qemu) info registers
iininfinfoinfo info rinfo reinfo reginfo regiinfo regisinfo registinfo registeinfo registerinfo registers
RAX=0000000000000000 RBX=0000000000000000 RCX=0000000000000000 RDX=0000000007ed5e20
RSI=0000000007233018 RDI=0000000007233018 RBP=0000000007234418 RSP=0000000007ec1360
R8 =0000000006211630 R9 =0000000000001000 R10=0000000007e00000 R11=0000000007ed6ea0
R12=0000000007ec1588 R13=0000000007ec1598 R14=0000000007ec1708 R15=0000000000000000
RIP=000000000620f72f RFL=00000202 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0038 0000000000000000 ffffffff 00af9a00 DPL=0 CS64 [-R-]
SS =0030 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0030 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0030 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0030 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT=     0000000007bee698 00000047
IDT=     000000000782e018 00000fff
CR0=80000033 CR2=0000000000000000 CR3=0000000007c01000 CR4=00000668
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
EFER=0000000000000500
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=00000000069940180000000000000000 XMM01=00000000000000000000000000000000
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000
XMM08=00000000000000000000000000000000 XMM09=00000000000000000000000000000000
XMM10=00000000000000000000000000000000 XMM11=00000000000000000000000000000000
XMM12=00000000000000000000000000000000 XMM13=00000000000000000000000000000000
XMM14=00000000000000000000000000000000 XMM15=00000000000000000000000000000000
(qemu)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;次に、既存のUEFIアプリをboot loaderとして、haltするだけの最小のカーネルを作ってロードする。boot loaderはプロジェクトのルートに&lt;code&gt;main.rs&lt;/code&gt;として配置しているので、カーネルはsrcディレクトリを作ってそこに置く。&lt;/p&gt;

&lt;p&gt;rustにもexternがある。externなしだとABIがRustのものになるが、&lt;code&gt;extern "C"&lt;/code&gt;するとSystem ABIになる。ドキュメントにはFFI用途と書いてあるが、自作OS用途でも大丈夫なはず。&lt;/p&gt;

&lt;p&gt;ちなみにNightlyだと&lt;code&gt;llvm_asm&lt;/code&gt;もあるらしい。&lt;br&gt;
&lt;a href="https://doc.rust-lang.org/unstable-book/library-features/llvm-asm.html"&gt;https://doc.rust-lang.org/unstable-book/library-features/llvm-asm.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ここからはloaderとkernelを分けて作るために、&lt;a href="https://doc.rust-lang.org/cargo/reference/workspaces.html"&gt;cargoのworkspace機能&lt;/a&gt;を使うことにした。&lt;br&gt;
&lt;a href="https://stackoverflow.com/a/53139624/15289527"&gt;StackOverflow&lt;/a&gt;によると、&lt;a href="https://github.com/tokio-rs/tokio/blob/master/Cargo.toml"&gt;tokio&lt;/a&gt;が参考になるらしい。&lt;/p&gt;

&lt;p&gt;workspaceでtagetがrootに一個だけなのは仕様らしい。&lt;br&gt;
&lt;a href="https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html"&gt;https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The workspace has one target directory at the top level for the compiled artifacts to be placed into; the adder package doesn’t have its own target directory. Even if we were to run cargo build from inside the adder directory, the compiled artifacts would still end up in add/target rather than add/adder/target. Cargo structures the target directory in a workspace like this because the crates in a workspace are meant to depend on each other. If each crate had its own target directory, each crate would have to recompile each of the other crates in the workspace to have the artifacts in its own target directory. By sharing one target directory, the crates can avoid unnecessary rebuilding.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;freestandingオプションを探してたら、ちょうどそれのサイトを見つけた。&lt;br&gt;
&lt;a href="https://os.phil-opp.com/ja/freestanding-rust-binary/"&gt;https://os.phil-opp.com/ja/freestanding-rust-binary/&lt;/a&gt;&lt;br&gt;
必要なことは全部ここに書いてあった。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Rust コンパイラが _start という名前の関数を実際に出力するように、#[no_mangle] attributeを用いて名前修飾を無効にします。&lt;/p&gt;

&lt;p&gt;戻り値の型である ! は関数が発散している、つまり値を返すことができないことを意味しています。エントリポイントはどの関数からも呼び出されず、OS またはブートローダから直接呼び出されるので、これは必須です。なので、値を返す代わりに、エントリポイントは例えば OS の exit システムコールを呼び出します。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;と思ったんだけど、&lt;code&gt;x86_64-efl&lt;/code&gt;をターゲットにしたカーネルのコンパイルができなかったので今日はここまで。&lt;/p&gt;

</description>
      <category>rust</category>
    </item>
    <item>
      <title>Rustで自作OS 3日目</title>
      <dc:creator>YT</dc:creator>
      <pubDate>Sun, 04 Jul 2021 09:39:19 +0000</pubDate>
      <link>https://dev.to/ytannai/rust-os-3-2jmd</link>
      <guid>https://dev.to/ytannai/rust-os-3-2jmd</guid>
      <description>&lt;p&gt;"第2章 EDK II入門とメモリマップ"を進めていく。&lt;br&gt;
自作OS本を読んだところ、USBブートするためにBoot Loaderを作っていくようで、昨日までで作ったUEFIアプリをEDK IIで書き直すらしい。&lt;br&gt;
昨日出てきたOVMFはUEFI BIOSのOSS実装で、EDK IIはUEFI BIOS上で動くアプリだけでなく、UEFI BIOS自体を開発するためにも使われるとのこと。&lt;/p&gt;

&lt;p&gt;Rustで書くときにどうすれば良いのか調べたが、いまいちピンとこない。そもそもUEFIとEDK IIがよく分かってない。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/rust-osdev/uefi-rs"&gt;uefi crate&lt;/a&gt;を使った昨日時点で&lt;code&gt;.efi&lt;/code&gt;出力が得られている。&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtu.be/dCu0-frSURE"&gt;Enabling Rust for UEFI Firmware - Webinar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rust-osdev/bootloader"&gt;rust-osdev/bootloader&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://osdev-jp.readthedocs.io/ja/latest/2017/create-uefi-app-with-edk2.html"&gt;osdev-jp&lt;/a&gt;を見ると、&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;スタンドアロンの UEFI アプリは UEFI Shell が起動する前に起動することができます。OS のブートローダーを作る場合などはスタンドアロンとして構成します。&lt;/p&gt;

&lt;p&gt;スタンドアロンの UEFI アプリのエントリポイントは一般的な C 言語プログラムと違い、EFI_HANDLE と EFI_SYSTEM_TABLE * を引数として受け取ります。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;ということは、昨日までのuefi crateを使ったUEFIアプリはこの特徴を満たしているのでは？なんなら使用可能メモリを表示する過程でメモリマップを取得しているのでは？&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#![no_std]&lt;/span&gt;
&lt;span class="nd"&gt;#![no_main]&lt;/span&gt;
&lt;span class="nd"&gt;#![feature(asm)]&lt;/span&gt;
&lt;span class="nd"&gt;#![feature(abi_efiapi)]&lt;/span&gt;
&lt;span class="nd"&gt;#![feature(alloc)]&lt;/span&gt;

&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;crate&lt;/span&gt; &lt;span class="n"&gt;uefi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;crate&lt;/span&gt; &lt;span class="n"&gt;uefi_services&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;crate&lt;/span&gt; &lt;span class="n"&gt;rlibc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;crate&lt;/span&gt; &lt;span class="n"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;crate&lt;/span&gt; &lt;span class="k"&gt;log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;uefi&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;uefi&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;table&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;boot&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MemoryType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="k"&gt;log&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;EFI_PAGE_SIZE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0x1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[entry]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;uefi_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;_&lt;/span&gt;&lt;span class="n"&gt;image_handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;uefi&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;system_table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SystemTable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Boot&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Status&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;uefi_services&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;system_table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect_success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to initialize utils"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;system_table&lt;/span&gt;
        &lt;span class="nf"&gt;.stdout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.reset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.expect_success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to reset output buffer"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;rev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;system_table&lt;/span&gt;&lt;span class="nf"&gt;.uefi_revision&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;major&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rev&lt;/span&gt;&lt;span class="nf"&gt;.major&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;rev&lt;/span&gt;&lt;span class="nf"&gt;.minor&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="nd"&gt;info!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"UEFI {}.{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;major&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;memory_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;system_table&lt;/span&gt;&lt;span class="nf"&gt;.boot_services&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="nn"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SUCCESS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;memory_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;BootServices&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;map_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bt&lt;/span&gt;&lt;span class="nf"&gt;.memory_map_size&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;with_capacity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="nf"&gt;.set_len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;_&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;desc_iter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bt&lt;/span&gt;
        &lt;span class="nf"&gt;.memory_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.expect_success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to retrieve UEFI memory map"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;descriptors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;desc_iter&lt;/span&gt;&lt;span class="nf"&gt;.copied&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="py"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;_&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;assert&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;descriptors&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"Memory map is empty"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;info!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"efi: usable memory ranges ({} total)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;descriptors&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="n"&gt;descriptors&lt;/span&gt;
        &lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.for_each&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;descriptor&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;descriptor&lt;/span&gt;&lt;span class="py"&gt;.ty&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nn"&gt;MemoryType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;CONVENTIONAL&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;descriptor&lt;/span&gt;&lt;span class="py"&gt;.page_count&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;EFI_PAGE_SIZE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;end_address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;descriptor&lt;/span&gt;&lt;span class="py"&gt;.phys_start&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nd"&gt;info!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="s"&gt;"&amp;gt; {:#x} - {:#x} ({} KiB)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;descriptor&lt;/span&gt;&lt;span class="py"&gt;.phys_start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end_address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;
                &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="mi"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;適当に写経してたから&lt;code&gt;uefi::table::boot&lt;/code&gt;とか使ってるのに気づかなかった。&lt;br&gt;
この構成でブートローダーとして機能するかはわからないので、とりあえず本を読み進める。&lt;br&gt;
&lt;a href="https://gil0mendes.io/blog/an-efi-app-a-bit-rusty/#the-app-itself"&gt;元になったブログ&lt;/a&gt;でもメモリマップ取得までやってたので、UEFIアプリのHello Worldは画面表示だけでなくメモリマップまでなのかもしれない。&lt;br&gt;
ちなみに自作OS本ではメモリマップをファイルに保存するUEFIアプリを作ってた。&lt;/p&gt;

&lt;p&gt;EDK IIを使ってるかは分からないが、今回の場合はueif crateを使ってboot loaderを作れればそれで良さそう。&lt;/p&gt;

</description>
      <category>rust</category>
    </item>
    <item>
      <title>Rustで自作OS 2日目</title>
      <dc:creator>YT</dc:creator>
      <pubDate>Sat, 03 Jul 2021 07:08:56 +0000</pubDate>
      <link>https://dev.to/ytannai/rust-os-2-48je</link>
      <guid>https://dev.to/ytannai/rust-os-2-48je</guid>
      <description>&lt;p&gt;今日は文字を表示するUEFIアプリを作るところから。自作OS本ではまだ1日目。&lt;br&gt;
&lt;a href="https://gil0mendes.io/blog/an-efi-app-a-bit-rusty/#the-app-itself"&gt;https://gil0mendes.io/blog/an-efi-app-a-bit-rusty/#the-app-itself&lt;/a&gt; を進めていく。&lt;br&gt;
Hello Worldに手を加えるところから。&lt;br&gt;
&lt;code&gt;#![...]&lt;/code&gt;は&lt;code&gt;attribute&lt;/code&gt;のようで、&lt;code&gt;#![no_std] is a crate-level attribute that indicates that the crate will link to the core-crate instead of the std-crate.&lt;/code&gt;とのこと。ベアメタル環境ではつける必要がある。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#![feature(asm)]&lt;/code&gt;でインラインアセンブリを書けるようにする(&lt;a href="https://doc.rust-lang.org/unstable-book/library-features/asm.html"&gt;The Rust Unstable Book&lt;/a&gt;)。&lt;br&gt;
&lt;code&gt;#![feature(abi_efapi)]&lt;/code&gt;のページはタイトルだけで中身からっぽだった。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#![no_std]&lt;/span&gt;              &lt;span class="c"&gt;// std libを使わない&lt;/span&gt;
&lt;span class="nd"&gt;#![no_main]&lt;/span&gt;             &lt;span class="c"&gt;// UEFI向けエントリポイントに変更する&lt;/span&gt;
&lt;span class="nd"&gt;#![feature(asm)]&lt;/span&gt;        &lt;span class="c"&gt;// inline assemblyを呼べる&lt;/span&gt;
&lt;span class="nd"&gt;#![feature(abi_efiapi)]&lt;/span&gt; &lt;span class="c"&gt;// よくわからないがABIを揃えるような名前&lt;/span&gt;

&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;crate&lt;/span&gt; &lt;span class="n"&gt;uefi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="n"&gt;crate&lt;/span&gt; &lt;span class="n"&gt;uefi_services&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;uefi&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[entry]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;uefi_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;_&lt;/span&gt;&lt;span class="n"&gt;image_handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;uefi&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;system_table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SystemTable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Boot&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Status&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="nn"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SUCCESS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;これを元ブログのPythonスクリプトで&lt;code&gt;build &amp;amp; run&lt;/code&gt;するんだけど、OVMFのファイルが生成されなくて失敗した。&lt;br&gt;
OFMFについて調べる。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://wiki.archlinux.jp/index.php/OVMF_%E3%81%AB%E3%82%88%E3%82%8B_PCI_%E3%83%91%E3%82%B9%E3%82%B9%E3%83%AB%E3%83%BC"&gt;OVMFによるPCIパススルー - archlinux wiki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gihyo.jp/admin/serial/01/ubuntu-recipe/0441"&gt;QEMU/KVMでUEFIファームウェアを使う - gihyo.jp&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;元ブログを読み返すと、見落としがあることがわかった。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;QEMU doesn’t come with OVMF, so it requires to installing it on your PC or get a pre-built image from the Internet, it’s possible to download it from my test repository.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://github.com/gil0mendes/Initium/tree/rust"&gt;元リポジトリ&lt;/a&gt;からダウンロードしてくるとrunコマンドでQEMUが動いた。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5N32I7pC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h2uqqaa0js055bgsphpn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5N32I7pC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h2uqqaa0js055bgsphpn.png" alt="Screen Shot 2021-07-03 at 14.27.16"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;次は文字を表示させる。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.rs/log/0.4.14/log/"&gt;log crate&lt;/a&gt;を入れて&lt;code&gt;info!&lt;/code&gt;マクロでログを表示できるようになった。&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zuyD198R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ug5ouypas43d9g6tzfet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zuyD198R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ug5ouypas43d9g6tzfet.png" alt="Screen Shot 2021-07-03 at 16.07.53"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
    </item>
    <item>
      <title>Rustで自作OS 1日目</title>
      <dc:creator>YT</dc:creator>
      <pubDate>Tue, 29 Jun 2021 15:40:12 +0000</pubDate>
      <link>https://dev.to/ytannai/rust-os-1-dje</link>
      <guid>https://dev.to/ytannai/rust-os-1-dje</guid>
      <description>&lt;p&gt;最近コード書いてなかったので、Rustの勉強を兼ねて自作OS本をやってみる。&lt;br&gt;
&lt;a href="https://www.amazon.co.jp/dp/B08Z3MNR9J"&gt;https://www.amazon.co.jp/dp/B08Z3MNR9J&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;環境はIntel macとIntelliJ。&lt;br&gt;
適当にリポジトリを作ってRustのHello Worldが動くように設定を終わらせる。&lt;br&gt;
&lt;a href="https://github.com/ytannai/kabos"&gt;https://github.com/ytannai/kabos&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;自作OS本はUEFIアプリをCで書くサンプルから始まるんだけど、Rustで書き直すところで止まった。&lt;/p&gt;

&lt;p&gt;ちなみにCargo.tomlでeditionという、バージョン的なものを指定できるらしい。&lt;/p&gt;

&lt;p&gt;普通に&lt;code&gt;rustup init&lt;/code&gt;したら2018だったので、試しに2021をしてみたらnaightlyにする必要があるようなので、&lt;code&gt;rustup toolchain install nightly&lt;/code&gt;でrelease channelを変えてみる。&lt;br&gt;
インストールしたら&lt;code&gt;rustup default nightly&lt;/code&gt;で適用する。*envの機能を公式でサポートしてるのが良い。&lt;/p&gt;

&lt;p&gt;この時点でCargo.tomlは以下のようになっている。これでHello Worldを再実行できた。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;cargo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;features&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"edition2021"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;package&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"kabos"&lt;/span&gt;
&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.0"&lt;/span&gt;
&lt;span class="n"&gt;edition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2021"&lt;/span&gt;

&lt;span class="cs"&gt;# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"kabos"&lt;/span&gt;
&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"main.rs"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;IntelliJがよく統合されていて、今のところ快適。&lt;/p&gt;

&lt;p&gt;で、UEFIに戻る。ライブラリが見つかった。&lt;br&gt;
&lt;a href="https://github.com/rust-osdev/uefi-rs"&gt;https://github.com/rust-osdev/uefi-rs&lt;/a&gt;&lt;br&gt;
このREADMEにあるブログを参考に、Cargo.tomlのdependenciesセクションへ依存関係を追加する。あと、unstable featureを使う設定もする。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;uefi&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.11.0"&lt;/span&gt;
&lt;span class="py"&gt;uefi-services&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.8.0"&lt;/span&gt;

&lt;span class="nn"&gt;[unstable]&lt;/span&gt;
&lt;span class="py"&gt;build-std&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"core"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"compiler_builtins"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"alloc"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;この時点でもう一度Hello Worldを実行してみる。実行はできるが、依存が増えたからかコンパイルに少し時間がかかるようになった。&lt;br&gt;
キャッシュされるのか、初回だけのようだ。&lt;/p&gt;

&lt;p&gt;依存にrlibcも追加すると、いよいよベアメタル感が出てくる。&lt;/p&gt;

&lt;p&gt;もう眠いので今日はここまで。次回はUEFIアプリの実装。&lt;br&gt;
&lt;a href="https://gil0mendes.io/blog/an-efi-app-a-bit-rusty/#the-app-itself"&gt;https://gil0mendes.io/blog/an-efi-app-a-bit-rusty/#the-app-itself&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
    </item>
  </channel>
</rss>
