Revise fs script;

Delete some unused files.
This commit is contained in:
Lu Sitong 2021-03-07 19:26:46 +08:00
parent 1858a86b82
commit f11911fca7
21 changed files with 122 additions and 494 deletions

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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脚本自动完成上述操作。

View File

@ -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 卡的原有数据与文件系统!

20
fs.sh
View File

@ -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

View File

@ -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.

View File

@ -24,7 +24,9 @@ void
fileinit(void)
{
initlock(&ftable.lock, "ftable");
#ifdef DEBUG
printf("fileinit\n");
#endif
}
// Allocate a file structure.

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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) {

View File

@ -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);
}

View File

@ -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

View File

@ -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
}

View File

@ -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.

View File

@ -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

View File

@ -1,307 +0,0 @@
// Copyright (c) 2006-2019 Frans Kaashoek, Robert Morris, Russ Cox,
// Massachusetts Institute of Technology
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#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);
}

View File

@ -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