diff --git a/Makefile b/Makefile index ec9b615..bdbb0f1 100644 --- a/Makefile +++ b/Makefile @@ -98,7 +98,7 @@ endif # Compile Kernel $T/kernel: $(OBJS) $(linker) $U/initcode - if [ ! -d "./target" ]; then mkdir target; fi + @if [ ! -d "./target" ]; then mkdir target; fi @$(LD) $(LDFLAGS) -T $(linker) -o $T/kernel $(OBJS) @$(OBJDUMP) -S $T/kernel > $T/kernel.asm @$(OBJDUMP) -t $T/kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $T/kernel.sym @@ -130,7 +130,7 @@ QEMUOPTS = -machine virt -bios $(RUSTSBI) -kernel $T/kernel -m 128M -smp $(CPUS) QEMUOPTS += -drive file=fs.img,if=none,format=raw,id=x0 QEMUOPTS += -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0 -run: build fs.img +run: build ifeq ($(platform), k210) @$(OBJCOPY) $T/kernel --strip-all -O binary $(image) @$(OBJCOPY) $(RUSTSBI) --strip-all -O binary $(k210) @@ -142,9 +142,6 @@ else @$(QEMU) $(QEMUOPTS) endif -fs.img: $(UPROGS) - @./fs.sh - $U/initcode: $U/initcode.S $(CC) $(CFLAGS) -march=rv64g -nostdinc -I. -Ikernel -c $U/initcode.S -o $U/initcode.o $(LD) $(LDFLAGS) -N -e start -Ttext 0 -o $U/initcode.out $U/initcode.o @@ -173,9 +170,6 @@ $U/_forktest: $U/forktest.o $(ULIB) $(LD) $(LDFLAGS) -N -e main -Ttext 0 -o $U/_forktest $U/forktest.o $U/ulib.o $U/usys.o $(OBJDUMP) -S $U/_forktest > $U/forktest.asm -mkfs/mkfs: mkfs/mkfs.c $K/include/fs.h $K/include/param.h - @gcc -Werror -Wall -I. -o mkfs/mkfs mkfs/mkfs.c - # Prevent deletion of intermediate files, e.g. cat.o, after first build, so # that disk image changes after first build are persistent until clean. More # details: @@ -205,23 +199,31 @@ UPROGS=\ # $U/_wc\ # $U/_zombie\ -UEXTRA = $U/xargstest.sh +userprogs: $(UPROGS) -userprogs: $(UEXTRA) $(UPROGS) +dst=/mnt # Make fs image -fs: mkfs/mkfs README $(UEXTRA) $(UPROGS) - @mkfs/mkfs fs.img README $(UEXTRA) $(UPROGS) - --include kernel/*.d user/*.d - -SDCARD ?= /dev/sdb +fs: $(UPROGS) + @if [ ! -f "fs.img" ]; then \ + echo "making fs image..."; \ + dd if=/dev/zero of=fs.img bs=512k count=1024; \ + mkfs.vfat -F 32 fs.img; fi + @sudo mount fs.img $(dst) + @if [ ! -d "$(dst)/bin" ]; then sudo mkdir $(dst)/bin; fi + @sudo cp $U/_init $(dst)/init + @sudo cp $U/_sh $(dst)/sh + @for file in $$( ls $U/_* ); do \ + sudo cp $$file $(dst)/bin/$${file#$U/_}; done + @sudo umount $(dst) # Write sdcard sdcard: fs - @echo "flashing into sd card..." - @sudo dd if=/dev/zero of=$(SDCARD) bs=1M count=50 - @sudo dd if=fs.img of=$(SDCARD) + @if [ "$(sd)" != "" ]; then \ + echo "flashing into sd card..."; \ + sudo dd if=fs.img of=$(sd); \ + else \ + echo "sd card not detected!"; fi clean: rm -f *.tex *.dvi *.idx *.aux *.log *.ind *.ilg \ @@ -229,6 +231,6 @@ clean: $T/* \ $U/initcode $U/initcode.out \ $K/kernel \ - mkfs/mkfs .gdbinit \ - $U/usys.S \ + .gdbinit \ + $U/usys.S \ $(UPROGS) diff --git a/README.md b/README.md index a9438da..12c310f 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,12 @@ make build ## Run on k210 board Instead of the original file system, xv6-k210 runs with FAT32. You might need an SD card with FAT32 format. To start `shell`, you need to rename the "_init" and "_sh" in the "/xv6-user" to "init" and "sh" after building, -then copy them to the root of your SD card. +then copy them to the root of your SD card. Or you can directly run the command as below with your SD card connected. + +Warning: this will format your SD card and clean your original data! +```bash +make sdcard sd="your SD card device's path" +``` To run on k210: ```bash @@ -56,16 +61,12 @@ may help you: [maixpy-doc](https://maixpy.sipeed.com/zh/get_started/env_install_ ## Run on qemu-system-riscv64 First, make sure `qemu-system-riscv64` is installed on your system. -Second, build the project to compile some user programs like `shell`. +Second, make a disk image file with FAT32 file system. ```bash -make build platform=qemu +make fs ``` -Then use the shell script `fs.sh`: -```bash -./fs.sh -``` -It will generate a disk image file `fs.img`, and copy some programs into the file. -As long as the `fs.img` exists, you don't need to run this script every time. +It will generate a disk image file `fs.img`, and compile some user programs like `shell` then copy them into the `fs.img`. +As long as the `fs.img` exists, you don't need to do this every time before running, unless you want to update it. Finally, start running. ```bash diff --git a/README_cn.md b/README_cn.md index 4303608..485c5c9 100644 --- a/README_cn.md +++ b/README_cn.md @@ -39,7 +39,13 @@ make build ## 在 k210 开发板上运行 Xv6-k210 采用 FAT32 文件系统,而不是其原本的文件系统。您需要一张 FAT32 格式的 SD 卡才能运行。 -在编译项目后,您需要将 “/xv6-user” 目录下的 “_init” 和 “_sh” 重命名为 “init” 和 “sh”,并拷贝至SD卡的根目录下。 +在编译项目后,您需要将 “/xv6-user” 目录下的 “_init” 和 “_sh” 重命名为 “init” 和 “sh”,并拷贝至 SD 卡的根目录下。 +或者,您可以直接运行以下命令。 + +警告:这会格式化您的 SD 卡并清除卡上的原有数据! +```bash +make sdcard sd="your SD card device's path" +``` 运行以下命令以在 `k210` 上运行: ```bash @@ -53,16 +59,12 @@ make run k210-serialport=`USB 端口`(默认是 ttyUSB0) Ps: 在 `Linux` 上这个端口大部分情况是 `ttyUSB0`, 如果您使用 `Windows` 或者 `MacOS`,这个文档可以帮助到您:[maixpy-doc](https://maixpy.sipeed.com/zh/get_started/env_install_driver.html#) ## 在 qemu-system-riscv64 模拟器上运行 -首先,确保 `qemu-system-riscv64` 已经下载到您的机器上并且加到了环境变量中。 -其次,编译项目生成用户程序,如 `shell` 等。 +首先,确保 `qemu-system-riscv64` 已经下载到您的机器上并且加到了环境变量中; +其次,需要一个 FAT32 磁盘镜像文件; ```bash -make build platform=qemu +make fs ``` -然后运行 `fs.sh` 脚本: -```bash -./fs.sh -``` -该脚本会生成一个镜像文件 `fs.img` 并将编译好的用户程序拷贝至其中。只要 `fs.img` 存在并且不需要修改,您不必每次都使用这个脚本。 +这会生成一个镜像文件 `fs.img` ,编译一些用户程序(如 `shell`)并拷贝至镜像中。只要 `fs.img` 存在并且不需要修改,您不必每次运行前都执行这个命令。 最后,开始运行: ```bash diff --git a/doc/构建调试-文件系统.md b/doc/构建调试-文件系统.md index 1814b76..a96d3a4 100644 --- a/doc/构建调试-文件系统.md +++ b/doc/构建调试-文件系统.md @@ -16,32 +16,5 @@ 对FAT32的支持只是一个简单的实现,还未经过严格的测试,存在许多不足。这里需要说明几点。 -+ 为了简单起见,目前新建文件时无法生成时间戳、未计算文件名校验和、未完成长文件名到短文件名的转换; ++ 为了简单起见,目前新建文件时无法生成时间戳,将长文件名转换到短文件名时未排重(这会影响较低版本的 FAT 系统); + FAT32的文件属性不支持设备类型,而原xv6文件系统中有`mknod`系统调用新建一个设备,并可以使用`open`打开。控制台输入输出就是这样打开的。为打开控制台标准输入输出,我们改用了另一种实现,即直接在内存中初始化控制台。 - -## 如何在qemu上挂载文件镜像 - -首先需要一个FAT32文件镜像,在Linux下可以通过`dd`命令和`mkfs`命令生成一个镜像,将生成的fs.img文件放在xv6-k210目录下即可。 - -```bash -$ dd if=/dev/zero of=fs.img bs=512k count=2048 -$ mkfs.vfat -F 32 fs.img -``` -注意:`dd`命令中的`bs`和`count`的参数只是参考,这会生成1GB的镜像。 - -## 如何在镜像中存入用户程序 - -首先通过`mount`命令,将镜像挂载到你指定的目录(这里以/mnt为例),然后将build之后xv6-user目录下文件名以"\_"为前缀的用户程序拷贝至镜像中,再取消挂载以保存写入结果即可。也可以在镜像中建立一些文本文件进行读测试。 - -注意:必须将xv6-user目录下的"\_init"拷贝至镜像根目录中,并且重命名为"init"(这是xv6原本的设定,目前我们暂未更改),还需拷贝"\_sh"至镜像中,才能启动shell。编写的用户程序也需要放在xv6-user目录下,同时需要添加至Makefile的`UPROGS`目标中,才能连同内核一起编译链接。 - -```bash -$ make build -$ (sudo)mount fs.img /mnt -$ (sudo)cp xv6-user/_init /mnt/init -$ (sudo)cp xv6-user/_sh /mnt -$ (sudo)cp xv6-user/... /mnt -$ ... -$ (sudo)umount /mnt -``` -PS:可以通过执行fs.sh脚本自动完成上述操作。 diff --git a/doc/用户使用-文件系统.md b/doc/用户使用-文件系统.md new file mode 100644 index 0000000..9bcae65 --- /dev/null +++ b/doc/用户使用-文件系统.md @@ -0,0 +1,34 @@ + +## 如何在qemu上挂载文件镜像 + +首先需要一个FAT32文件镜像,在Linux下可以通过`dd`命令和`mkfs`命令生成一个镜像,将生成的fs.img文件放在xv6-k210目录下即可。 + +```bash +$ dd if=/dev/zero of=fs.img bs=512k count=2048 +$ mkfs.vfat -F 32 fs.img +``` +注意:`dd`命令中的`bs`和`count`的参数只是参考,这会生成1GB的镜像。 + +## 如何在镜像中存入用户程序 + +首先通过`mount`命令,将镜像挂载到你指定的目录(这里以/mnt为例),然后将build之后xv6-user目录下文件名以"\_"为前缀的用户程序拷贝至镜像中,再取消挂载以保存写入结果即可。也可以在镜像中建立一些文本文件进行读测试。 + +注意:必须将xv6-user目录下的"\_init"拷贝至镜像根目录中,并且重命名为"init"(这是xv6原本的设定,目前我们暂未更改),还需拷贝"\_sh"至镜像中,才能启动shell。编写的用户程序也需要放在xv6-user目录下,同时需要添加至Makefile的`UPROGS`目标中,才能连同内核一起编译链接。 + +```bash +$ make build +$ (sudo)mount fs.img /mnt +$ (sudo)cp xv6-user/_init /mnt/init +$ (sudo)cp xv6-user/_sh /mnt +$ (sudo)cp xv6-user/... /mnt +$ ... +$ (sudo)umount /mnt +``` +PS:现已可以通过执行 `make fs` 自动完成上述操作。 + +## 如何在 SD 卡中存入用户程序 +将上述操作生成的 `fs.img` 写入 SD 卡即可。可以执行操作: +```bash +make sdcard sd="your SD card device" +``` +警告:这会覆盖 SD 卡的原有数据与文件系统! \ No newline at end of file diff --git a/fs.sh b/fs.sh deleted file mode 100755 index 1605b9f..0000000 --- a/fs.sh +++ /dev/null @@ -1,20 +0,0 @@ -if [ ! -f "fs.img" ]; then - dd if=/dev/zero of=fs.img bs=512k count=1024 - mkfs.vfat -F 32 fs.img -fi - -sudo mount fs.img /mnt -sudo mkdir /mnt/bin -sudo cp ./xv6-user/_init /mnt/init -sudo cp ./xv6-user/_sh /mnt/sh -sudo cp ./xv6-user/_cat /mnt/bin/cat -sudo cp ./xv6-user/_echo /mnt/bin/echo -sudo cp ./xv6-user/_grep /mnt/bin/grep -sudo cp ./xv6-user/_ls /mnt/bin/ls -sudo cp ./xv6-user/_kill /mnt/bin/kill -sudo cp ./xv6-user/_mkdir /mnt/bin/mkdir -sudo cp ./xv6-user/_xargs /mnt/bin/xargs -sudo cp ./xv6-user/_rm /mnt/bin/rm -sudo cp ./xv6-user/_sleep /mnt/bin/sleep -sudo cp ./xv6-user/_find /mnt/bin/find -sudo umount /mnt diff --git a/kernel/bio.c b/kernel/bio.c index 72c15de..6903632 100644 --- a/kernel/bio.c +++ b/kernel/bio.c @@ -55,7 +55,9 @@ binit(void) bcache.head.next->prev = b; bcache.head.next = b; } + #ifdef DEBUG printf("binit\n"); + #endif } // Look through buffer cache for block on device dev. diff --git a/kernel/file.c b/kernel/file.c index 7b29a57..eed3617 100644 --- a/kernel/file.c +++ b/kernel/file.c @@ -24,7 +24,9 @@ void fileinit(void) { initlock(&ftable.lock, "ftable"); + #ifdef DEBUG printf("fileinit\n"); + #endif } // Allocate a file structure. diff --git a/kernel/fpioa.c b/kernel/fpioa.c index 3a67549..b620a09 100644 --- a/kernel/fpioa.c +++ b/kernel/fpioa.c @@ -4936,5 +4936,7 @@ void fpioa_pin_init() { fpioa_set_function(26, FUNC_SPI0_D1); fpioa_set_function(32, FUNC_GPIOHS7); fpioa_set_function(29, FUNC_SPI0_SS3); + #ifdef DEBUG printf("fpioa_pin_init\n"); + #endif } \ No newline at end of file diff --git a/kernel/kalloc.c b/kernel/kalloc.c index 5d2c1c2..de0b01b 100644 --- a/kernel/kalloc.c +++ b/kernel/kalloc.c @@ -29,7 +29,9 @@ kinit() initlock(&kmem.lock, "kmem"); // printf("kernel_end: %p, phystop: %p\n", kernel_end, (void*)PHYSTOP); freerange(kernel_end, (void*)PHYSTOP); + #ifdef DEBUG printf("kinit\n"); + #endif } void diff --git a/kernel/main.c b/kernel/main.c index 79d6b6b..005b927 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -25,7 +25,9 @@ main(unsigned long hartid, unsigned long dtb_pa) consoleinit(); printfinit(); // init a lock for printf print_logo(); + #ifdef DEBUG printf("hart %d enter main()...\n", hartid); + #endif kinit(); // physical page allocator kvminit(); // create kernel page table kvminithart(); // turn on paging @@ -33,7 +35,6 @@ main(unsigned long hartid, unsigned long dtb_pa) trapinithart(); // install kernel trap vector timerinit(); // set up timer interrupt handler procinit(); - #ifndef QEMU fpioa_pin_init(); device_init(dtb_pa, hartid); @@ -41,28 +42,28 @@ main(unsigned long hartid, unsigned long dtb_pa) plicinit(); plicinithart(); #endif - disk_init(); - binit(); // buffer cache fileinit(); // file table - userinit(); // first user process - printf("hart 0 init done\n"); + for(int i = 1; i < NCPU; i++) { unsigned long mask = 1 << i; sbi_send_ipi(&mask); } __sync_synchronize(); started = 1; - } else + } + else { // hart 1 while (started == 0) ; __sync_synchronize(); + #ifdef DEBUG printf("hart %d enter main()...\n", hartid); + #endif kvminithart(); trapinithart(); timerinit(); // set up timer interrupt handler diff --git a/kernel/plic.c b/kernel/plic.c index 2b9d5c7..7648409 100644 --- a/kernel/plic.c +++ b/kernel/plic.c @@ -16,7 +16,9 @@ plicinit(void) // set desired IRQ priorities non-zero (otherwise disabled). *(uint32*)(PLIC + UART0_IRQ*4) = 1; *(uint32*)(PLIC + VIRTIO0_IRQ*4) = 1; + #ifdef DEBUG printf("plicinit\n"); + #endif } void @@ -28,7 +30,9 @@ plicinithart(void) *(uint32*)PLIC_SENABLE(hart)= (1 << UART0_IRQ) | (1 << VIRTIO0_IRQ); // set this hart's S-mode priority threshold to 0. *(uint32*)PLIC_SPRIORITY(hart) = 0; + #ifdef DEBUG printf("plicinithart\n"); + #endif } // ask the PLIC what interrupt we should serve. diff --git a/kernel/proc.c b/kernel/proc.c index 343b893..3530520 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -62,7 +62,9 @@ procinit(void) p->kstack = va; } kvminithart(); + #ifdef DEBUG printf("procinit\n"); + #endif } // Must be called with interrupts disabled, @@ -286,7 +288,9 @@ userinit(void) p->state = RUNNABLE; release(&p->lock); + #ifdef DEBUG printf("userinit\n"); + #endif } // Grow or shrink user memory by n bytes. diff --git a/kernel/sdcard.c b/kernel/sdcard.c index 2c46151..854e5d4 100644 --- a/kernel/sdcard.c +++ b/kernel/sdcard.c @@ -311,12 +311,12 @@ void sdcard_init(void) { int result = sd_init(); initlock(&sdcard_lock, "sdcard"); - if (0 == result) { - printf("sdcard_init\n"); - } - else { + if (0 != result) { panic("sdcard_init failed"); } + #ifdef DEBUG + printf("sdcard_init\n"); + #endif } void sdcard_read_sector(uint8 *buf, int sectorno) { diff --git a/kernel/start.c b/kernel/start.c deleted file mode 100644 index 0a2ebc9..0000000 --- a/kernel/start.c +++ /dev/null @@ -1,84 +0,0 @@ - -#include "include/types.h" -#include "include/param.h" -#include "include/memlayout.h" -#include "include/riscv.h" -#include "include/defs.h" - -void main(); -void timerinit(); - -// entry.S needs one stack per CPU. -__attribute__ ((aligned (16))) char stack0[4096 * NCPU]; - -// scratch area for timer interrupt, one per CPU. -uint64 mscratch0[NCPU * 32]; - -// assembly code in kernelvec.S for machine-mode timer interrupt. -extern void timervec(); - -// entry.S jumps here in machine mode on stack0. -void -start() -{ - // set M Previous Privilege mode to Supervisor, for mret. - unsigned long x = r_mstatus(); - x &= ~MSTATUS_MPP_MASK; - x |= MSTATUS_MPP_S; - w_mstatus(x); - - // set M Exception Program Counter to main, for mret. - // requires gcc -mcmodel=medany - w_mepc((uint64)main); - - // disable paging for now. - w_satp(0); - - // delegate all interrupts and exceptions to supervisor mode. - w_medeleg(0xffff); - w_mideleg(0xffff); - w_sie(r_sie() | SIE_SEIE | SIE_STIE | SIE_SSIE); - - // ask for clock interrupts. - //timerinit(); - - // keep each CPU's hartid in its tp register, for cpuid(). - int id = r_mhartid(); - w_tp(id); - - // switch to supervisor mode and jump to main(). - asm volatile("mret"); -} - -// set up to receive timer interrupts in machine mode, -// which arrive at timervec in kernelvec.S, -// which turns them into software interrupts for -// devintr() in trap.c. -void -timerinit() -{ - // each CPU has a separate source of timer interrupts. - int id = r_mhartid(); - - // ask the CLINT for a timer interrupt. - int interval = 1000000; // cycles; about 1/10th second in qemu. - *(uint64*)CLINT_MTIMECMP(id) = *(uint64*)CLINT_MTIME + interval; - - // prepare information in scratch[] for timervec. - // scratch[0..3] : space for timervec to save registers. - // scratch[4] : address of CLINT MTIMECMP register. - // scratch[5] : desired interval (in cycles) between timer interrupts. - uint64 *scratch = &mscratch0[32 * id]; - scratch[4] = CLINT_MTIMECMP(id); - scratch[5] = interval; - w_mscratch((uint64)scratch); - - // set the machine-mode trap handler. - w_mtvec((uint64)timervec); - - // enable machine-mode interrupts. - w_mstatus(r_mstatus() | MSTATUS_MIE); - - // enable machine-mode timer interrupts. - w_mie(r_mie() | MIE_MTIE); -} diff --git a/kernel/timer.c b/kernel/timer.c index 77cacbb..c20a7b5 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -15,7 +15,9 @@ void timerinit() { // enable supervisor-mode timer interrupts. w_sie(r_sie() | SIE_STIE); set_next_timeout(); + #ifdef DEBUG printf("timerinit\n"); + #endif } void diff --git a/kernel/trap.c b/kernel/trap.c index 047a12b..29b26f3 100644 --- a/kernel/trap.c +++ b/kernel/trap.c @@ -23,7 +23,9 @@ void trapinit(void) { initlock(&tickslock, "time"); + #ifdef DEBUG printf("trapinit\n"); + #endif } // set up to take exceptions and traps while in the kernel. @@ -33,7 +35,9 @@ trapinithart(void) w_stvec((uint64)kernelvec); w_sstatus(r_sstatus() | SSTATUS_SIE); w_sie(r_sie() | SIE_SEIE | SIE_SSIE); + #ifdef DEBUG printf("trapinithart\n"); + #endif } // @@ -240,6 +244,7 @@ supervisor_external_handler() { int irq = *(uint32*)(PLIC + 0x04); if(irq == UARTHS_IRQ) { // UARTHS + printf("[supervisor_external_handler]\n"); } else { @@ -276,5 +281,7 @@ void device_init(unsigned long pa, uint64 hartid) { *((uint32*)0x0c000028) = 0x7; *((uint32*)0x0c201000) = 0x0; #endif + #ifdef DEBUG printf("device init\n"); + #endif } \ No newline at end of file diff --git a/kernel/virtio_disk.c b/kernel/virtio_disk.c index c68753c..dad1bd6 100644 --- a/kernel/virtio_disk.c +++ b/kernel/virtio_disk.c @@ -111,7 +111,9 @@ virtio_disk_init(void) disk.free[i] = 1; // plic.c and trap.c arrange for interrupts from VIRTIO0_IRQ. + #ifdef DEBUG printf("virtio_disk_init\n"); + #endif } // find a free descriptor, mark it non-free, return its index. diff --git a/kernel/vm.c b/kernel/vm.c index af50709..134408e 100644 --- a/kernel/vm.c +++ b/kernel/vm.c @@ -75,7 +75,9 @@ kvminit() kvmmap(TRAMPOLINE, (uint64)trampoline, PGSIZE, PTE_R | PTE_X); // kvmmap(TRAMPOLINE, (uint64)trampoline, PGSIZE, PTE_R | PTE_X); + #ifdef DEBUG printf("kvminit\n"); + #endif } // Switch h/w page table register to the kernel's page table, @@ -86,7 +88,9 @@ kvminithart() w_satp(MAKE_SATP(kernel_pagetable)); // reg_info(); sfence_vma(); + #ifdef DEBUG printf("kvminithart\n"); + #endif } // Return the address of the PTE in page table pagetable diff --git a/mkfs/mkfs.c b/mkfs/mkfs.c deleted file mode 100644 index fc0eb28..0000000 --- a/mkfs/mkfs.c +++ /dev/null @@ -1,307 +0,0 @@ -// Copyright (c) 2006-2019 Frans Kaashoek, Robert Morris, Russ Cox, -// Massachusetts Institute of Technology -#include -#include -#include -#include -#include -#include - -#define stat xv6_stat // avoid clash with host struct stat -#include "kernel/include/types.h" -#include "kernel/include/fs.h" -#include "kernel/include/stat.h" -#include "kernel/include/param.h" - -#ifndef static_assert -#define static_assert(a, b) do { switch (0) case 0: case (a): ; } while (0) -#endif - -#define NINODES 200 - -// Disk layout: -// [ boot block | sb block | log | inode blocks | free bit map | data blocks ] - -int nbitmap = FSSIZE/(BSIZE*8) + 1; -int ninodeblocks = NINODES / IPB + 1; -int nlog = LOGSIZE; -int nmeta; // Number of meta blocks (boot, sb, nlog, inode, bitmap) -int nblocks; // Number of data blocks - -int fsfd; -struct superblock sb; -char zeroes[BSIZE]; -uint freeinode = 1; -uint freeblock; - - -void balloc(int); -void wsect(uint, void*); -void winode(uint, struct dinode*); -void rinode(uint inum, struct dinode *ip); -void rsect(uint sec, void *buf); -uint ialloc(ushort type); -void iappend(uint inum, void *p, int n); - -// convert to intel byte order -ushort -xshort(ushort x) -{ - ushort y; - uchar *a = (uchar*)&y; - a[0] = x; - a[1] = x >> 8; - return y; -} - -uint -xint(uint x) -{ - uint y; - uchar *a = (uchar*)&y; - a[0] = x; - a[1] = x >> 8; - a[2] = x >> 16; - a[3] = x >> 24; - return y; -} - -int -main(int argc, char *argv[]) -{ - int i, cc, fd; - uint rootino, inum, off; - struct dirent de; - char buf[BSIZE]; - struct dinode din; - - - static_assert(sizeof(int) == 4, "Integers must be 4 bytes!"); - - if(argc < 2){ - fprintf(stderr, "Usage: mkfs fs.img files...\n"); - exit(1); - } - - assert((BSIZE % sizeof(struct dinode)) == 0); - assert((BSIZE % sizeof(struct dirent)) == 0); - - fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666); - if(fsfd < 0){ - perror(argv[1]); - exit(1); - } - - // 1 fs block = 1 disk sector - nmeta = 2 + nlog + ninodeblocks + nbitmap; - nblocks = FSSIZE - nmeta; - - sb.magic = FSMAGIC; - sb.size = xint(FSSIZE); - sb.nblocks = xint(nblocks); - sb.ninodes = xint(NINODES); - sb.nlog = xint(nlog); - sb.logstart = xint(2); - sb.inodestart = xint(2+nlog); - sb.bmapstart = xint(2+nlog+ninodeblocks); - - printf("nmeta %d (boot, super, log blocks %u inode blocks %u, bitmap blocks %u) blocks %d total %d\n", - nmeta, nlog, ninodeblocks, nbitmap, nblocks, FSSIZE); - - freeblock = nmeta; // the first free block that we can allocate - - for(i = 0; i < FSSIZE; i++) - wsect(i, zeroes); - - memset(buf, 0, sizeof(buf)); - memmove(buf, &sb, sizeof(sb)); - wsect(1, buf); - - rootino = ialloc(T_DIR); - assert(rootino == ROOTINO); - - bzero(&de, sizeof(de)); - de.inum = xshort(rootino); - strcpy(de.name, "."); - iappend(rootino, &de, sizeof(de)); - - bzero(&de, sizeof(de)); - de.inum = xshort(rootino); - strcpy(de.name, ".."); - iappend(rootino, &de, sizeof(de)); - - for(i = 2; i < argc; i++){ - // get rid of "user/" - char *shortname; - if(strncmp(argv[i], "xv6-user/", 9) == 0) - shortname = argv[i] + 9; - else - shortname = argv[i]; - - assert(index(shortname, '/') == 0); - - if((fd = open(argv[i], 0)) < 0){ - perror(argv[i]); - exit(1); - } - - // Skip leading _ in name when writing to file system. - // The binaries are named _rm, _cat, etc. to keep the - // build operating system from trying to execute them - // in place of system binaries like rm and cat. - if(shortname[0] == '_') - shortname += 1; - - inum = ialloc(T_FILE); - - bzero(&de, sizeof(de)); - de.inum = xshort(inum); - strncpy(de.name, shortname, DIRSIZ); - iappend(rootino, &de, sizeof(de)); - - while((cc = read(fd, buf, sizeof(buf))) > 0) - iappend(inum, buf, cc); - - close(fd); - } - - // fix size of root inode dir - rinode(rootino, &din); - off = xint(din.size); - off = ((off/BSIZE) + 1) * BSIZE; - din.size = xint(off); - winode(rootino, &din); - - balloc(freeblock); - - exit(0); -} - -void -wsect(uint sec, void *buf) -{ - if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE){ - perror("lseek"); - exit(1); - } - if(write(fsfd, buf, BSIZE) != BSIZE){ - perror("write"); - exit(1); - } -} - -void -winode(uint inum, struct dinode *ip) -{ - char buf[BSIZE]; - uint bn; - struct dinode *dip; - - bn = IBLOCK(inum, sb); - rsect(bn, buf); - dip = ((struct dinode*)buf) + (inum % IPB); - *dip = *ip; - wsect(bn, buf); -} - -void -rinode(uint inum, struct dinode *ip) -{ - char buf[BSIZE]; - uint bn; - struct dinode *dip; - - bn = IBLOCK(inum, sb); - rsect(bn, buf); - dip = ((struct dinode*)buf) + (inum % IPB); - *ip = *dip; -} - -void -rsect(uint sec, void *buf) -{ - if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE){ - perror("lseek"); - exit(1); - } - if(read(fsfd, buf, BSIZE) != BSIZE){ - perror("read"); - exit(1); - } -} - -uint -ialloc(ushort type) -{ - uint inum = freeinode++; - struct dinode din; - - bzero(&din, sizeof(din)); - din.type = xshort(type); - din.nlink = xshort(1); - din.size = xint(0); - winode(inum, &din); - return inum; -} - -void -balloc(int used) -{ - uchar buf[BSIZE]; - int i; - - printf("balloc: first %d blocks have been allocated\n", used); - assert(used < BSIZE*8); - bzero(buf, BSIZE); - for(i = 0; i < used; i++){ - buf[i/8] = buf[i/8] | (0x1 << (i%8)); - } - printf("balloc: write bitmap block at sector %d\n", sb.bmapstart); - wsect(sb.bmapstart, buf); -} - -#define min(a, b) ((a) < (b) ? (a) : (b)) - -void -iappend(uint inum, void *xp, int n) -{ - char *p = (char*)xp; - uint fbn, off, n1; - struct dinode din; - char buf[BSIZE]; - uint indirect[NINDIRECT]; - uint x; - - rinode(inum, &din); - off = xint(din.size); - // printf("append inum %d at off %d sz %d\n", inum, off, n); - while(n > 0){ - fbn = off / BSIZE; - assert(fbn < MAXFILE); - if(fbn < NDIRECT){ - if(xint(din.addrs[fbn]) == 0){ - din.addrs[fbn] = xint(freeblock++); - } - x = xint(din.addrs[fbn]); - } else { - if(xint(din.addrs[NDIRECT]) == 0){ - din.addrs[NDIRECT] = xint(freeblock++); - } - rsect(xint(din.addrs[NDIRECT]), (char*)indirect); - if(indirect[fbn - NDIRECT] == 0){ - indirect[fbn - NDIRECT] = xint(freeblock++); - wsect(xint(din.addrs[NDIRECT]), (char*)indirect); - } - x = xint(indirect[fbn-NDIRECT]); - } - n1 = min(n, (fbn + 1) * BSIZE - off); - rsect(x, buf); - bcopy(p, buf + off - (fbn * BSIZE), n1); - wsect(x, buf); - n -= n1; - off += n1; - p += n1; - } - din.size = xint(off); - winode(inum, &din); -} diff --git a/xv6-user/sh.c b/xv6-user/sh.c index c22e2ee..fdb2c12 100644 --- a/xv6-user/sh.c +++ b/xv6-user/sh.c @@ -62,11 +62,6 @@ int fork1(void); // Fork but panics on failure. void panic(char*); struct cmd *parsecmd(char*); -#ifndef QEMU -char platform[] = "k210"; -#else -char platform[] = "qemu"; -#endif char mycwd[128]; int @@ -254,7 +249,7 @@ runcmd(struct cmd *cmd) int getcmd(char *buf, int nbuf) { - fprintf(2, "-> xv6@%s: %s $ ", platform, mycwd); + fprintf(2, "-> %s $ ", mycwd); memset(buf, 0, nbuf); gets(buf, nbuf); if(buf[0] == 0) // EOF