From: acevest Date: Thu, 11 Apr 2024 11:54:47 +0000 (+0800) Subject: 添加生成rootfs的工具 X-Git-Url: http://zhaoyanbai.com/repos/nsupdate.html?a=commitdiff_plain;h=a8258b99b9c40eda2b194a4b5f1bc6a34b255ef8;p=kernel.git 添加生成rootfs的工具 --- diff --git a/.gitignore b/.gitignore index 603e279..e603669 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,6 @@ bochsout.txt .vscode/settings.json *.iso **/serial_monitor/serial_monitor +**/mkrootfs/mkrootfs +initrd +rootfs diff --git a/boot/boot.c b/boot/boot.c index a29fab4..1ee713a 100644 --- a/boot/boot.c +++ b/boot/boot.c @@ -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; diff --git a/boot/multiboot.S b/boot/multiboot.S index 3791f26..a12335f 100644 --- a/boot/multiboot.S +++ b/boot/multiboot.S @@ -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 index 0000000..3cae102 --- /dev/null +++ b/kernel/time.c @@ -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); +} diff --git a/mkiso.sh b/mkiso.sh index 00f6c95..7091b36 100755 --- a/mkiso.sh +++ b/mkiso.sh @@ -1,4 +1,5 @@ - +#!/bin/bash +# if [ $# -ne 1 ]; then docker ps -a echo "input containerid " diff --git a/scripts/iso.grub.cfg b/scripts/iso.grub.cfg index a68cfbc..614e154 100644 --- a/scripts/iso.grub.cfg +++ b/scripts/iso.grub.cfg @@ -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 } diff --git a/scripts/mkiso.sh b/scripts/mkiso.sh index fb98eb0..0f6270b 100755 --- a/scripts/mkiso.sh +++ b/scripts/mkiso.sh @@ -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 index 0000000..2450a10 --- /dev/null +++ b/scripts/mkrootfs/go.mod @@ -0,0 +1,2 @@ +module mkrootfs + diff --git a/scripts/mkrootfs/main.go b/scripts/mkrootfs/main.go new file mode 100644 index 0000000..9a413b4 --- /dev/null +++ b/scripts/mkrootfs/main.go @@ -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) +}