]> Zhao Yanbai Git Server - kernel.git/commitdiff
添加生成rootfs的工具
authoracevest <zhaoyanbai@126.com>
Thu, 11 Apr 2024 11:54:47 +0000 (19:54 +0800)
committeracevest <zhaoyanbai@126.com>
Fri, 12 Apr 2024 04:46:38 +0000 (12:46 +0800)
.gitignore
boot/boot.c
boot/multiboot.S
kernel/time.c [new file with mode: 0644]
mkiso.sh
scripts/iso.grub.cfg
scripts/mkiso.sh
scripts/mkrootfs/go.mod [new file with mode: 0644]
scripts/mkrootfs/main.go [new file with mode: 0644]

index 603e27932cf5c3c3124fd2d4159e4da392ee37b6..e60366917b6801a175dad436b8a4f5ce8fcd3f85 100644 (file)
@@ -38,3 +38,6 @@ bochsout.txt
 .vscode/settings.json
 *.iso
 **/serial_monitor/serial_monitor
+**/mkrootfs/mkrootfs
+initrd
+rootfs
index a29fab4c63bcc85f3bcae836862a07418ec3ace6..1ee713a31cb3cf30299e368bd24958cc4c585f22 100644 (file)
@@ -110,6 +110,19 @@ void check_kernel(unsigned long addr, unsigned long magic) {
             strlcpy(boot_params.bootloader, ((struct multiboot_tag_string *)tag)->string,
                     sizeof(boot_params.bootloader));
             break;
+        case MULTIBOOT_TAG_TYPE_MODULE:
+            struct multiboot_tag_module *m = (struct multiboot_tag_module *)tag;
+            printk("module 0x%08x - 0x%08x size %u cmdline %s\n", m->mod_start, m->mod_end, m->size, m->cmdline);
+            // TODO 在操作系统中保留这段内存
+            uint32_t *mod_magic = m->mod_start + 0;
+            uint32_t *mod_timestamp = m->mod_start + 8;
+            uint32_t *mod_file_entry_cnt = m->mod_start + 12;
+            char *mod_name = m->mod_start + 16;
+            printk("module magic %08x timestamp %u file entry cnt %u name %s \n", *mod_magic, *mod_timestamp,
+                   *mod_file_entry_cnt, mod_name);
+            void timestamp_to_date(uint32_t ts);
+            timestamp_to_date(*mod_timestamp);
+            break;
         case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
             mminfo = (struct multiboot_tag_basic_meminfo *)tag;
             // KB to Bytes
@@ -144,6 +157,11 @@ void check_kernel(unsigned long addr, unsigned long magic) {
         case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
             printk("frame buffer\n");
             break;
+        // case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
+        //     struct multiboot_tag_elf_sections *s = (struct multiboot_tag_elf_sections *)tag;
+        //     break;
+        case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
+            printk("load base addr %08x\n", ((struct multiboot_tag_load_base_addr *)tag)->load_base_addr);
         default:
             support = false;
             break;
index 3791f26901897607632fc2febbd296321694104a..a12335fb3465a67cf39dfa45fc5968f3824db361 100644 (file)
@@ -188,7 +188,14 @@ multiboot2_header_bgn:
     // .long 32
     // .framebuffer_tag_end:
 
-    .align 8
+    // // .align 2
+    .multiboot2_header_tag_module:
+    .short MULTIBOOT_HEADER_TAG_MODULE_ALIGN
+    .short 0
+    .long  8
+    .long 0
+
+    .align 2
     .multiboot2_tag_end:
     .short MULTIBOOT_HEADER_TAG_END
     .short 0
diff --git a/kernel/time.c b/kernel/time.c
new file mode 100644 (file)
index 0000000..3cae102
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * ------------------------------------------------------------------------
+ *   File Name: time.c
+ *      Author: Zhao Yanbai
+ *              2024-04-11 19:27:39 Thursday CST
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
+
+#include "printk.h"
+#include "types.h"
+
+#define MINUTE 60
+#define HOUR (60 * MINUTE)
+#define DAY (24 * HOUR)
+#define YEAR (365 * DAY)
+
+uint32_t days_in_month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+int is_leap_year(uint32_t year) { return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); }
+
+void timestamp_to_date(uint32_t timestamp) {
+    // 将时间戳转换为东8区时间
+    timestamp += 8 * HOUR;
+
+    uint32_t seconds = timestamp % 60;
+    uint32_t minutes = (timestamp / MINUTE) % 60;
+    uint32_t hours = (timestamp / HOUR) % 24;
+    uint32_t days_since_1970 = timestamp / DAY;
+
+    uint32_t year = 1970;
+    while (days_since_1970 >= (is_leap_year(year) ? 366 : 365)) {
+        days_since_1970 -= (is_leap_year(year) ? 366 : 365);
+        year++;
+    }
+
+    if (is_leap_year(year)) {
+        days_in_month[2] = 29;
+    } else {
+        days_in_month[2] = 28;
+    }
+
+    uint32_t month = 1;
+    while (days_since_1970 >= days_in_month[month]) {
+        days_since_1970 -= days_in_month[month];
+        month++;
+    }
+
+    uint32_t day = days_since_1970 + 1;
+
+    printk("%u-%02u-%02u %02u:%02u:%02u\n", year, month, day, hours, minutes, seconds);
+}
index 00f6c956b7a00975923f2846ae497ad2386ee1b5..7091b3617c905f978d4964fab66d2b8205f273b6 100755 (executable)
--- a/mkiso.sh
+++ b/mkiso.sh
@@ -1,4 +1,5 @@
-
+#!/bin/bash
+#
 if [ $# -ne 1 ]; then
     docker ps -a
     echo "input containerid "
index a68cfbc54bbaa5bcab7aa184ec3c4d9142112dda..614e154b0aab1c0e71facf8ab0f51443a8adbfaf 100644 (file)
@@ -11,5 +11,6 @@ menuentry 'Kernel' --class os {
     #set gfxpayload=1024x768x32
     #insmod all_video
     multiboot2 /boot/Kernel root=hda7 delay=2
+    module2 /boot/rootfs rootfs
     boot
 }
index fb98eb0e3a198e6d10402a402047a89d69e0bd4d..0f6270bc9dbb0d3539bb85d5c97631c32f5322ce 100755 (executable)
@@ -1,7 +1,11 @@
+#!/bin/bash
 # 在父目录运行
 # 这个代码必需要在x86的linux机器上运行
 # 因为如果在其它机器上运行,其grub就不是x86版本
+source ~/.bashrc
 mkdir -p /tmp/iso/boot/grub/
 cp scripts/iso.grub.cfg /tmp/iso/boot/grub/grub.cfg
 cp KERNEL.ELF /tmp/iso/boot/Kernel
+mkrootfs -path initrd --name rootfs
+cp rootfs /tmp/iso/boot/
 grub2-mkrescue -o kernel.iso /tmp/iso/
diff --git a/scripts/mkrootfs/go.mod b/scripts/mkrootfs/go.mod
new file mode 100644 (file)
index 0000000..2450a10
--- /dev/null
@@ -0,0 +1,2 @@
+module mkrootfs
+
diff --git a/scripts/mkrootfs/main.go b/scripts/mkrootfs/main.go
new file mode 100644 (file)
index 0000000..9a413b4
--- /dev/null
@@ -0,0 +1,229 @@
+package main
+
+import (
+       "encoding/binary"
+       "flag"
+       "fmt"
+       "io"
+       "log"
+       "os"
+       "path/filepath"
+       "strings"
+       "time"
+)
+
+const MagicCode = 0x66179BF8
+
+type FileHeader struct {
+       Magic        uint32
+       HeaderSize   uint32
+       Timestamp    uint32
+       FileEntryCnt uint32
+       Name         string
+}
+
+func (f *FileHeader) CalculateHeaderSize() {
+       f.HeaderSize = uint32(4 + 4 + 4 + 4 + len(f.Name))
+}
+
+type FileType uint32
+
+const (
+       FileTypeUnknown FileType = iota
+       FileTypeNormal
+       FileTypeDir
+       FileTypeSymlink
+)
+
+func (t FileType) String() string {
+       s := ""
+       switch t {
+       case FileTypeNormal:
+               s += "normal"
+       case FileTypeDir:
+               s += "dir"
+       case FileTypeSymlink:
+               s += "symlink"
+       default:
+               s += "unknown"
+       }
+       s = fmt.Sprintf("%10v:%v", s, uint32(t))
+       return s
+}
+
+type FileEntry struct {
+       EntrySize uint32
+       FileType
+       FileName string // 生成在initrd文件中的文件名
+       FileSize uint32
+       Offset   uint32 // 在文件中的偏移
+       RealPath string // 这个不写到输出文件中
+}
+
+func (e FileEntry) String() string {
+       s := fmt.Sprintf("%v:%v:%v", e.EntrySize, e.FileType, e.FileName)
+       return s
+}
+
+func main() {
+
+       var inputPath string
+       var outputFileName string
+
+       flag.StringVar(&inputPath, "path", "", "Path to the folder to be packed")
+       flag.StringVar(&outputFileName, "name", "", "Name of the generated file")
+
+       flag.Parse()
+
+       if inputPath == "" || outputFileName == "" {
+               flag.Usage()
+               return
+       }
+
+       // 获取当前目录
+       currentDir, err := os.Getwd()
+       if err != nil {
+               log.Fatal(err)
+       }
+
+       // 计算相对路径
+       relPath, err := filepath.Rel(currentDir, filepath.Join(currentDir, inputPath))
+       if err != nil {
+               log.Fatal(err)
+       }
+
+       pathPrefix := relPath
+
+       var entries []FileEntry
+
+       err = filepath.Walk(pathPrefix, func(filePath string, info os.FileInfo, err error) error {
+               if err != nil {
+                       return err
+               }
+
+               fileType := FileTypeUnknown
+               fileSize := uint32(0)
+               switch {
+               case info.Mode().IsRegular():
+                       fileType = FileTypeNormal
+                       fileInfo, err := os.Stat(filePath)
+                       if err != nil {
+                               log.Fatal(err)
+                       }
+                       fileSize = uint32(fileInfo.Size())
+               case info.Mode().IsDir():
+                       fileType = FileTypeDir
+               case info.Mode()&os.ModeSymlink != 0:
+                       fileType = FileTypeSymlink
+                       log.Fatalf("unsupport symlink file")
+               default:
+                       log.Fatalf("unsupport file type for %v", filePath)
+               }
+
+               if filePath == pathPrefix {
+                       return nil
+               }
+
+               path := strings.TrimPrefix(filePath, pathPrefix)
+
+               entry := FileEntry{
+                       EntrySize: uint32(8 + len(path)),
+                       FileType:  fileType,
+                       FileName:  path,
+                       FileSize:  fileSize,
+                       RealPath:  filePath,
+               }
+               entries = append(entries, entry)
+
+               fmt.Printf("%v\n", entry)
+
+               return nil
+       })
+
+       if err != nil {
+               log.Fatal(err)
+       }
+
+       outputFile, err := os.Create(outputFileName)
+       if err != nil {
+               log.Fatal(err)
+       }
+       defer outputFile.Close()
+
+       // 写入文件头
+       var hdr FileHeader
+       hdr.Magic = MagicCode
+       hdr.HeaderSize = 0
+       hdr.Timestamp = uint32(time.Now().Unix())
+       hdr.FileEntryCnt = uint32(len(entries))
+       hdr.Name = outputFileName + "\x00"
+       hdr.CalculateHeaderSize()
+
+       binary.Write(outputFile, binary.LittleEndian, hdr.Magic)
+       if err != nil {
+               log.Fatal(err)
+       }
+       binary.Write(outputFile, binary.LittleEndian, hdr.HeaderSize)
+       if err != nil {
+               log.Fatal(err)
+       }
+       binary.Write(outputFile, binary.LittleEndian, hdr.Timestamp)
+       if err != nil {
+               log.Fatal(err)
+       }
+       binary.Write(outputFile, binary.LittleEndian, hdr.FileEntryCnt)
+       if err != nil {
+               log.Fatal(err)
+       }
+       _, err = io.WriteString(outputFile, hdr.Name)
+       if err != nil {
+               log.Fatal(err)
+       }
+
+       // // 写入文件项数量
+       // err = binary.Write(outputFile, binary.LittleEndian, uint32(len(entries)))
+       // if err != nil {
+       //      log.Fatal(err)
+       // }
+
+       // 写入每个文件项
+       currentOffset := uint32(4 + len(entries)*12)
+       for _, entry := range entries {
+               entry.Offset = currentOffset
+
+               err = binary.Write(outputFile, binary.LittleEndian, entry.EntrySize)
+               if err != nil {
+                       log.Fatal(err)
+               }
+
+               err = binary.Write(outputFile, binary.LittleEndian, entry.FileType)
+               if err != nil {
+                       log.Fatal(err)
+               }
+
+               _, err = outputFile.WriteString(entry.FileName)
+               if err != nil {
+                       log.Fatal(err)
+               }
+
+               currentOffset += entry.FileSize
+       }
+
+       // 逐个读取文件并追加到 outputFileName
+       for _, entry := range entries {
+               if entry.FileType == 1 {
+                       file, err := os.Open(entry.RealPath)
+                       if err != nil {
+                               log.Fatal(err)
+                       }
+                       defer file.Close()
+
+                       _, err = io.Copy(outputFile, file)
+                       if err != nil {
+                               log.Fatal(err)
+                       }
+               }
+       }
+
+       fmt.Printf("Binary file '%v' created.\n", outputFileName)
+}