├── .DS_Store ├── .gitignore ├── README.md ├── docs ├── GUI文档.pdf ├── SHELL文档.pdf ├── 操作系统展示ppt.pptx └── 音频播放文档.pdf └── xv6 ├── .asm ├── .sym ├── 9.bmp ├── BUGS ├── HZK16.fnt ├── LICENSE ├── Makefile ├── Notes ├── README ├── TRICKS ├── _shell ├── asm.h ├── bg.bmp ├── bio.c ├── bitmap.c ├── bitmap.h ├── blank.bmp ├── bootasm.S ├── bootmain.c ├── buf.h ├── cal.c ├── cat.c ├── clickable.c ├── clickable.h ├── close.bmp ├── common.c ├── common.h ├── console.c ├── context.c ├── context.h ├── copy.bmp ├── cp.c ├── createfile.bmp ├── createfolder.bmp ├── cty.txt ├── cut.bmp ├── cuth ├── date.h ├── decode.c ├── decode.h ├── decodemp3.c ├── defs.h ├── desktop.c ├── dot-bochsrc ├── down.bmp ├── drawingAPI.c ├── drawingAPI.h ├── echo.c ├── editor.c ├── elf.h ├── entry.S ├── entryother.S ├── exec.c ├── fcntl.h ├── file.c ├── file.h ├── file_icon_big.bmp ├── file_icon_small.bmp ├── finder.c ├── finder.h ├── folder_icon_big.bmp ├── folder_icon_small.bmp ├── foldericon.bmp ├── forktest.c ├── fs.c ├── fs.h ├── gamecenter.bmp ├── gdbutil ├── grep.c ├── hankaku.txt ├── huffman.c ├── huffman.h ├── ide.c ├── in.mp3 ├── init.c ├── initcode.S ├── ioapic.c ├── kalloc.c ├── kbd.c ├── kbd.h ├── kernel.ld ├── kill.c ├── lapic.c ├── layer3.c ├── ln.c ├── log.c ├── ls.c ├── main.c ├── math.c ├── math.h ├── memide.c ├── memlayout.h ├── message.c ├── message.h ├── mkdir.c ├── mkfs.c ├── mmu.h ├── mouse.c ├── mouse.h ├── mp.c ├── mp.h ├── mp3dec.c ├── music.bmp ├── mv.c ├── notes.bmp ├── param.h ├── paste.bmp ├── pause.bmp ├── pause.c ├── picirq.c ├── picviewer.c ├── picviewer.h ├── pipe.c ├── play.bmp ├── play.c ├── playmp3.c ├── playmusic.c ├── pr.pl ├── printf.c ├── printpcs ├── proc.c ├── proc.h ├── qemu.wav ├── qian.wav ├── ren.c ├── rename.bmp ├── rm.c ├── rolldown.bmp ├── rollup.bmp ├── runoff ├── runoff.list ├── runoff.spec ├── runoff1 ├── save.bmp ├── search.bmp ├── setting.bmp ├── sh.c ├── shell_gui.c ├── shell_sh.c ├── show1 ├── sign.pl ├── sleep1.p ├── sound.c ├── sound.h ├── spinlock.c ├── spinlock.h ├── spinp ├── splice.c ├── stat.h ├── stressfs.c ├── string.c ├── swtch.S ├── symlink.patch ├── sysaudio.c ├── syscall.c ├── syscall.h ├── sysfile.c ├── sysmp3.c ├── sysproc.c ├── syswindow.c ├── tags ├── test.wav ├── text.c ├── timer.c ├── toc.ftr ├── toc.hdr ├── touch.c ├── trap.c ├── trapasm.S ├── traps.h ├── trash.bmp ├── txtEditor_gui.c ├── types.h ├── uart.c ├── ulib.c ├── umalloc.c ├── up.bmp ├── up1.bmp ├── uptime.c ├── user.h ├── usertests.c ├── usys.S ├── vectors.pl ├── vesamode.c ├── vesamode.h ├── viewingmode1.bmp ├── viewingmode2.bmp ├── vm.c ├── wc.c ├── window.c ├── window.h ├── windowStyle.h ├── x86.h └── zombie.c /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | 34 | # Temp files of some editors 35 | *~ 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XV6 2 | 软件学院 2015年计算机系统软件 XV6 系统优化开发 3 | 4 | ----- 5 | 6 | xv6最新原码地址:https://github.com/mit-pdos/xv6-public 7 | 8 | ----- 9 | 10 | ##小组分工: 11 | 1. MP3(徐京傲组、马希鹏组、高贤达组) 12 | 2. GUI(夏英达组、陈彤宇组、竺俊超组) 13 | 3. Shell(柯豪组、洪政佑组) 14 | 15 | ----- 16 | 17 | ## 申请加入 18 | 1. 点击[Issues#1](https://github.com/THSS13/XV6/issues/1) 19 | - 按照要求回复 20 | - 等待管理员邀请 21 | - 收到邮件后点击链接同意请求 22 | 23 | ## 项目需求 24 | 1. 将二字班去年选题二(在resource分支下的Project_2文件夹)的xv6内核进行升级。 25 | - 将二字班去年选题一(在resource分支下的Project_1文件夹)的代码整合进升级后的代码中。 26 | - 做一些提升功能。 27 | 28 | ----- 29 | ## 合作方式 30 | ### 需求的提出: 31 | 根据我们的项目需求提出细分的任务目标,将目标以及描述以issue的方式提出。 32 | 补充任务: 提交BUG 33 | ### 任务的认领: 34 | 预估自己的能力大小,在issues页面以回帖的形式进行认领。如任务粒度过大,可以将其细分提出新的issue再认领其中一部分。 35 | ### 完成开发: 36 | 根据自己认领的任务,**建立相应的分支**,分支名为 "issue %d"%issueID 并完成相应开发。 37 | 只做与任务有关的最小改动,注意不要修改无关文件。 38 | ### 合并代码: 39 | 完成相应的开发以后需进行: 40 | 1. 合并与上游代码保证无冲突 41 | 2. 进行充分测试至少保证编译 42 | 3. 提交PR请求 43 | 如果管理员进行合并时与上游冲突请合并冲,需要撤回并重复以上步骤 44 | 45 | 46 | 47 | ## 任务清单(不定时更新) 48 | 1. 在第十周(11月22日)前将往届的Project2在自己的电脑上跑起来。(跑不起来的可以看一下[Issue#7](https://github.com/THSS13/XV6/issues/7)) 49 | 2. 在某一周前搞定代码整合(需求中的1和2)。 50 | -------------------------------------------------------------------------------- /docs/GUI文档.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/docs/GUI文档.pdf -------------------------------------------------------------------------------- /docs/SHELL文档.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/docs/SHELL文档.pdf -------------------------------------------------------------------------------- /docs/操作系统展示ppt.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/docs/操作系统展示ppt.pptx -------------------------------------------------------------------------------- /docs/音频播放文档.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/docs/音频播放文档.pdf -------------------------------------------------------------------------------- /xv6/.asm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/.asm -------------------------------------------------------------------------------- /xv6/9.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/9.bmp -------------------------------------------------------------------------------- /xv6/BUGS: -------------------------------------------------------------------------------- 1 | formatting: 2 | need to fix PAGEBREAK mechanism 3 | 4 | sh: 5 | can't always runcmd in child -- breaks cd. 6 | maybe should hard-code PATH=/ ? 7 | 8 | -------------------------------------------------------------------------------- /xv6/HZK16.fnt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/HZK16.fnt -------------------------------------------------------------------------------- /xv6/LICENSE: -------------------------------------------------------------------------------- 1 | The xv6 software is: 2 | 3 | Copyright (c) 2006-2009 Frans Kaashoek, Robert Morris, Russ Cox, 4 | Massachusetts Institute of Technology 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | -------------------------------------------------------------------------------- /xv6/Notes: -------------------------------------------------------------------------------- 1 | bochs 2.2.6: 2 | ./configure --enable-smp --enable-disasm --enable-debugger --enable-all-optimizations --enable-4meg-pages --enable-global-pages --enable-pae --disable-reset-on-triple-fault 3 | bochs CVS after 2.2.6: 4 | ./configure --enable-smp --enable-disasm --enable-debugger --enable-all-optimizations --enable-4meg-pages --enable-global-pages --enable-pae 5 | 6 | bootmain.c doesn't work right if the ELF sections aren't 7 | sector-aligned. so you can't use ld -N. and the sections may also need 8 | to be non-zero length, only really matters for tiny "kernels". 9 | 10 | kernel loaded at 1 megabyte. stack same place that bootasm.S left it. 11 | 12 | kinit() should find real mem size 13 | and rescue useable memory below 1 meg 14 | 15 | no paging, no use of page table hardware, just segments 16 | 17 | no user area: no magic kernel stack mapping 18 | so no copying of kernel stack during fork 19 | though there is a kernel stack page for each process 20 | 21 | no kernel malloc(), just kalloc() for user core 22 | 23 | user pointers aren't valid in the kernel 24 | 25 | are interrupts turned on in the kernel? yes. 26 | 27 | pass curproc explicitly, or implicit from cpu #? 28 | e.g. argument to newproc()? 29 | hmm, you need a global curproc[cpu] for trap() &c 30 | 31 | no stack expansion 32 | 33 | test running out of memory, process slots 34 | 35 | we can't really use a separate stack segment, since stack addresses 36 | need to work correctly as ordinary pointers. the same may be true of 37 | data vs text. how can we have a gap between data and stack, so that 38 | both can grow, without committing 4GB of physical memory? does this 39 | mean we need paging? 40 | 41 | perhaps have fixed-size stack, put it in the data segment? 42 | 43 | oops, if kernel stack is in contiguous user phys mem, then moving 44 | users' memory (e.g. to expand it) will wreck any pointers into the 45 | kernel stack. 46 | 47 | do we need to set fs and gs? so user processes can't abuse them? 48 | 49 | setupsegs() may modify current segment table, is that legal? 50 | 51 | trap() ought to lgdt on return, since currently only done in swtch() 52 | 53 | protect hardware interrupt vectors from user INT instructions? 54 | 55 | test out-of-fd cases for creating pipe. 56 | test pipe reader closes then write 57 | test two readers, two writers. 58 | test children being inherited by grandparent &c 59 | 60 | some sleep()s should be interruptible by kill() 61 | 62 | locks 63 | init_lock 64 | sequences CPU startup 65 | proc_table_lock 66 | also protects next_pid 67 | per-fd lock *just* protects count read-modify-write 68 | also maybe freeness? 69 | memory allocator 70 | printf 71 | 72 | in general, the table locks protect both free-ness and 73 | public variables of table elements 74 | in many cases you can use table elements w/o a lock 75 | e.g. if you are the process, or you are using an fd 76 | 77 | lock order 78 | per-pipe lock 79 | proc_table_lock fd_table_lock kalloc_lock 80 | console_lock 81 | 82 | do you have to be holding the mutex in order to call wakeup()? yes 83 | 84 | device interrupts don't clear FL_IF 85 | so a recursive timer interrupt is possible 86 | 87 | what does inode->busy mean? 88 | might be held across disk reads 89 | no-one is allowed to do anything to the inode 90 | protected by inode_table_lock 91 | inode->count counts in-memory pointers to the struct 92 | prevents inode[] element from being re-used 93 | protected by inode_table_lock 94 | 95 | blocks and inodes have ad-hoc sleep-locks 96 | provide a single mechanism? 97 | 98 | kalloc() can return 0; do callers handle this right? 99 | 100 | test: one process unlinks a file while another links to it 101 | test: one process opens a file while another deletes it 102 | test: deadlock d/.. vs ../d, two processes. 103 | test: dup() shared fd->off 104 | test: does echo foo > x truncate x? 105 | 106 | sh: ioredirection incorrect now we have pipes 107 | sh: chain of pipes won't work, also ugly that parent closes fdarray entries too 108 | sh: dynamic memory allocation? 109 | sh: should sh support ; () & 110 | sh: stop stdin on ctrl-d (for cat > y) 111 | 112 | really should have bdwrite() for file content 113 | and make some inode updates async 114 | so soft updates make sense 115 | 116 | disk scheduling 117 | echo foo > bar should truncate bar 118 | so O_CREATE should not truncate 119 | but O_TRUNC should 120 | 121 | make it work on a real machine 122 | release before acquire at end of sleep? 123 | check 2nd disk (i.e. if not in .bochsrc) 124 | -------------------------------------------------------------------------------- /xv6/README: -------------------------------------------------------------------------------- 1 | xv6 is a re-implementation of Dennis Ritchie's and Ken Thompson's Unix 2 | Version 6 (v6). xv6 loosely follows the structure and style of v6, 3 | but is implemented for a modern x86-based multiprocessor using ANSI C. 4 | 5 | ACKNOWLEDGMENTS 6 | 7 | xv6 is inspired by John Lions's Commentary on UNIX 6th Edition (Peer 8 | to Peer Communications; ISBN: 1-57398-013-7; 1st edition (June 14, 9 | 2000)). See also http://pdos.csail.mit.edu/6.828/2012/v6.html, which 10 | provides pointers to on-line resources for v6. 11 | 12 | xv6 borrows code from the following sources: 13 | JOS (asm.h, elf.h, mmu.h, bootasm.S, ide.c, console.c, and others) 14 | Plan 9 (entryother.S, mp.h, mp.c, lapic.c) 15 | FreeBSD (ioapic.c) 16 | NetBSD (console.c) 17 | 18 | The following people have made contributions: 19 | Russ Cox (context switching, locking) 20 | Cliff Frey (MP) 21 | Xiao Yu (MP) 22 | Nickolai Zeldovich 23 | Austin Clements 24 | 25 | In addition, we are grateful for the bug reports and patches contributed by 26 | Silas Boyd-Wickizer, Peter Froehlich, Shivam Handa, Anders Kaseorg, Eddie 27 | Kohler, Yandong Mao, Hitoshi Mitake, Carmi Merimovich, Joel Nider, Greg Price, 28 | Eldar Sehayek, Yongming Shen, Stephen Tu, and Zouchangwei. 29 | 30 | The code in the files that constitute xv6 is 31 | Copyright 2006-2014 Frans Kaashoek, Robert Morris, and Russ Cox. 32 | 33 | ERROR REPORTS 34 | 35 | If you spot errors or have suggestions for improvement, please send 36 | email to Frans Kaashoek and Robert Morris (kaashoek,rtm@csail.mit.edu). 37 | 38 | BUILDING AND RUNNING XV6 39 | 40 | To build xv6 on an x86 ELF machine (like Linux or FreeBSD), run "make". 41 | On non-x86 or non-ELF machines (like OS X, even on x86), you will 42 | need to install a cross-compiler gcc suite capable of producing x86 ELF 43 | binaries. See http://pdos.csail.mit.edu/6.828/2014/tools.html. 44 | Then run "make TOOLPREFIX=i386-jos-elf-". 45 | 46 | To run xv6, install the QEMU PC simulators. To run in QEMU, run "make qemu". 47 | 48 | To create a typeset version of the code, run "make xv6.pdf". This 49 | requires the "mpage" utility. See http://www.mesa.nl/pub/mpage/. 50 | -------------------------------------------------------------------------------- /xv6/TRICKS: -------------------------------------------------------------------------------- 1 | This file lists subtle things that might not be commented 2 | as well as they should be in the source code and that 3 | might be worth pointing out in a longer explanation or in class. 4 | 5 | --- 6 | 7 | [2009/07/12: No longer relevant; forkret1 changed 8 | and this is now cleaner.] 9 | 10 | forkret1 in trapasm.S is called with a tf argument. 11 | In order to use it, forkret1 copies the tf pointer into 12 | %esp and then jumps to trapret, which pops the 13 | register state out of the trap frame. If an interrupt 14 | came in between the mov tf, %esp and the iret that 15 | goes back out to user space, the interrupt stack frame 16 | would end up scribbling over the tf and whatever memory 17 | lay under it. 18 | 19 | Why is this safe? Because forkret1 is only called 20 | the first time a process returns to user space, and 21 | at that point, cp->tf is set to point to a trap frame 22 | constructed at the top of cp's kernel stack. So tf 23 | *is* a valid %esp that can hold interrupt state. 24 | 25 | If other tf's were used in forkret1, we could add 26 | a cli before the mov tf, %esp. 27 | 28 | --- 29 | 30 | In pushcli, must cli() no matter what. It is not safe to do 31 | 32 | if(cpus[cpu()].ncli == 0) 33 | cli(); 34 | cpus[cpu()].ncli++; 35 | 36 | because if interrupts are off then we might call cpu(), get 37 | rescheduled to a different cpu, look at cpus[oldcpu].ncli, 38 | and wrongly decide not to disable interrupts on the new cpu. 39 | 40 | Instead do 41 | 42 | cli(); 43 | cpus[cpu()].ncli++; 44 | 45 | always. 46 | 47 | --- 48 | 49 | There is a (harmless) race in pushcli, which does 50 | 51 | eflags = readeflags(); 52 | cli(); 53 | if(c->ncli++ == 0) 54 | c->intena = eflags & FL_IF; 55 | 56 | Consider a bottom-level pushcli. 57 | If interrupts are disabled already, then the right thing 58 | happens: read_eflags finds that FL_IF is not set, 59 | and intena = 0. If interrupts are enabled, then 60 | it is less clear that the right thing happens: 61 | the readeflags can execute, then the process 62 | can get preempted and rescheduled on another cpu, 63 | and then once it starts running, perhaps with 64 | interrupts disabled (can happen since the scheduler 65 | only enables interrupts once per scheduling loop, 66 | not every time it schedules a process), it will 67 | incorrectly record that interrupts *were* enabled. 68 | This doesn't matter, because if it was safe to be 69 | running with interrupts enabled before the context 70 | switch, it is still safe (and arguably more correct) 71 | to run with them enabled after the context switch too. 72 | 73 | In fact it would be safe if scheduler always set 74 | c->intena = 1; 75 | before calling swtch, and perhaps it should. 76 | 77 | --- 78 | 79 | The x86's processor-ordering memory model 80 | matches spin locks well, so no explicit memory 81 | synchronization instructions are required in 82 | acquire and release. 83 | 84 | Consider two sequences of code on different CPUs: 85 | 86 | CPU0 87 | A; 88 | release(lk); 89 | 90 | and 91 | 92 | CPU1 93 | acquire(lk); 94 | B; 95 | 96 | We want to make sure that: 97 | - all reads in B see the effects of writes in A. 98 | - all reads in A do *not* see the effects of writes in B. 99 | 100 | The x86 guarantees that writes in A will go out 101 | to memory before the write of lk->locked = 0 in 102 | release(lk). It further guarantees that CPU1 103 | will observe CPU0's write of lk->locked = 0 only 104 | after observing the earlier writes by CPU0. 105 | So any reads in B are guaranteed to observe the 106 | effects of writes in A. 107 | 108 | According to the Intel manual behavior spec, the 109 | second condition requires a serialization instruction 110 | in release, to avoid reads in A happening after giving 111 | up lk. No Intel SMP processor in existence actually 112 | moves reads down after writes, but the language in 113 | the spec allows it. There is no telling whether future 114 | processors will need it. 115 | 116 | --- 117 | 118 | The code in fork needs to read np->pid before 119 | setting np->state to RUNNABLE. The following 120 | is not a correct way to do this: 121 | 122 | int 123 | fork(void) 124 | { 125 | ... 126 | np->state = RUNNABLE; 127 | return np->pid; // oops 128 | } 129 | 130 | After setting np->state to RUNNABLE, some other CPU 131 | might run the process, it might exit, and then it might 132 | get reused for a different process (with a new pid), all 133 | before the return statement. So it's not safe to just 134 | "return np->pid". Even saving a copy of np->pid before 135 | setting np->state isn't safe, since the compiler is 136 | allowed to re-order statements. 137 | 138 | The real code saves a copy of np->pid, then acquires a lock 139 | around the write to np->state. The acquire() prevents the 140 | compiler from re-ordering. 141 | -------------------------------------------------------------------------------- /xv6/_shell: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/_shell -------------------------------------------------------------------------------- /xv6/asm.h: -------------------------------------------------------------------------------- 1 | // 2 | // assembler macros to create x86 segments 3 | // 4 | 5 | #define SEG_NULLASM \ 6 | .word 0, 0; \ 7 | .byte 0, 0, 0, 0 8 | 9 | // The 0xC0 means the limit is in 4096-byte units 10 | // and (for executable segments) 32-bit mode. 11 | #define SEG_ASM(type,base,lim) \ 12 | .word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \ 13 | .byte (((base) >> 16) & 0xff), (0x90 | (type)), \ 14 | (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff) 15 | 16 | #define STA_X 0x8 // Executable segment 17 | #define STA_E 0x4 // Expand down (non-executable segments) 18 | #define STA_C 0x4 // Conforming code segment (executable only) 19 | #define STA_W 0x2 // Writeable (non-executable segments) 20 | #define STA_R 0x2 // Readable (executable segments) 21 | #define STA_A 0x1 // Accessed 22 | -------------------------------------------------------------------------------- /xv6/bg.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/bg.bmp -------------------------------------------------------------------------------- /xv6/bio.c: -------------------------------------------------------------------------------- 1 | // Buffer cache. 2 | // 3 | // The buffer cache is a linked list of buf structures holding 4 | // cached copies of disk block contents. Caching disk blocks 5 | // in memory reduces the number of disk reads and also provides 6 | // a synchronization point for disk blocks used by multiple processes. 7 | // 8 | // Interface: 9 | // * To get a buffer for a particular disk block, call bread. 10 | // * After changing buffer data, call bwrite to write it to disk. 11 | // * When done with the buffer, call brelse. 12 | // * Do not use the buffer after calling brelse. 13 | // * Only one process at a time can use a buffer, 14 | // so do not keep them longer than necessary. 15 | // 16 | // The implementation uses three state flags internally: 17 | // * B_BUSY: the block has been returned from bread 18 | // and has not been passed back to brelse. 19 | // * B_VALID: the buffer data has been read from the disk. 20 | // * B_DIRTY: the buffer data has been modified 21 | // and needs to be written to disk. 22 | 23 | #include "types.h" 24 | #include "defs.h" 25 | #include "param.h" 26 | #include "spinlock.h" 27 | #include "buf.h" 28 | 29 | struct { 30 | struct spinlock lock; 31 | struct buf buf[NBUF]; 32 | 33 | // Linked list of all buffers, through prev/next. 34 | // head.next is most recently used. 35 | struct buf head; 36 | } bcache; 37 | 38 | void 39 | binit(void) 40 | { 41 | struct buf *b; 42 | 43 | initlock(&bcache.lock, "bcache"); 44 | 45 | //PAGEBREAK! 46 | // Create linked list of buffers 47 | bcache.head.prev = &bcache.head; 48 | bcache.head.next = &bcache.head; 49 | for(b = bcache.buf; b < bcache.buf+NBUF; b++){ 50 | b->next = bcache.head.next; 51 | b->prev = &bcache.head; 52 | b->dev = -1; 53 | bcache.head.next->prev = b; 54 | bcache.head.next = b; 55 | } 56 | } 57 | 58 | // Look through buffer cache for sector on device dev. 59 | // If not found, allocate a buffer. 60 | // In either case, return B_BUSY buffer. 61 | static struct buf* 62 | bget(uint dev, uint sector) 63 | { 64 | struct buf *b; 65 | 66 | acquire(&bcache.lock); 67 | 68 | loop: 69 | // Is the sector already cached? 70 | for(b = bcache.head.next; b != &bcache.head; b = b->next){ 71 | if(b->dev == dev && b->sector == sector){ 72 | if(!(b->flags & B_BUSY)){ 73 | b->flags |= B_BUSY; 74 | release(&bcache.lock); 75 | return b; 76 | } 77 | sleep(b, &bcache.lock); 78 | goto loop; 79 | } 80 | } 81 | 82 | // Not cached; recycle some non-busy and clean buffer. 83 | // "clean" because B_DIRTY and !B_BUSY means log.c 84 | // hasn't yet committed the changes to the buffer. 85 | for(b = bcache.head.prev; b != &bcache.head; b = b->prev){ 86 | if((b->flags & B_BUSY) == 0 && (b->flags & B_DIRTY) == 0){ 87 | b->dev = dev; 88 | b->sector = sector; 89 | b->flags = B_BUSY; 90 | release(&bcache.lock); 91 | return b; 92 | } 93 | } 94 | panic("bget: no buffers"); 95 | } 96 | 97 | // Return a B_BUSY buf with the contents of the indicated disk sector. 98 | struct buf* 99 | bread(uint dev, uint sector) 100 | { 101 | struct buf *b; 102 | 103 | b = bget(dev, sector); 104 | if(!(b->flags & B_VALID)) 105 | iderw(b); 106 | return b; 107 | } 108 | 109 | // Write b's contents to disk. Must be B_BUSY. 110 | void 111 | bwrite(struct buf *b) 112 | { 113 | if((b->flags & B_BUSY) == 0) 114 | panic("bwrite"); 115 | b->flags |= B_DIRTY; 116 | iderw(b); 117 | } 118 | 119 | // Release a B_BUSY buffer. 120 | // Move to the head of the MRU list. 121 | void 122 | brelse(struct buf *b) 123 | { 124 | if((b->flags & B_BUSY) == 0) 125 | panic("brelse"); 126 | 127 | acquire(&bcache.lock); 128 | 129 | b->next->prev = b->prev; 130 | b->prev->next = b->next; 131 | b->next = bcache.head.next; 132 | b->prev = &bcache.head; 133 | bcache.head.next->prev = b; 134 | bcache.head.next = b; 135 | 136 | b->flags &= ~B_BUSY; 137 | wakeup(b); 138 | 139 | release(&bcache.lock); 140 | } 141 | //PAGEBREAK! 142 | // Blank page. 143 | 144 | -------------------------------------------------------------------------------- /xv6/bitmap.h: -------------------------------------------------------------------------------- 1 | #ifndef BITMAP_H 2 | #define BITMAP_H 3 | 4 | #define WIDTHBYTES(bits) (((bits)+31)/32*4) 5 | typedef unsigned char BYTE; 6 | typedef unsigned short WORD; 7 | typedef unsigned long DWORD; 8 | typedef long LONG; 9 | 10 | //位图文件头信息结构定义 11 | //其中不包含文件类型信息(由于结构体的内存结构决定,要是加了的话将不能正确读取文件信息) 12 | typedef struct tagBITMAPFILEHEADER { 13 | WORD bfType;//固定为0x4d42 14 | DWORD bfSize; //文件大小 15 | WORD bfReserved1; //保留字,不考虑 16 | WORD bfReserved2; //保留字,同上 17 | DWORD bfOffBits; //实际位图数据的偏移字节数,即前三个部分长度之和 18 | } BITMAPFILEHEADER; 19 | 20 | //信息头BITMAPINFOHEADER,也是一个结构,其定义如下: 21 | typedef struct tagBITMAPINFOHEADER{ 22 | //public: 23 | DWORD biSize; //指定此结构体的长度,为40 24 | LONG biWidth; //位图宽 25 | LONG biHeight; //位图高 26 | WORD biPlanes; //平面数,为1 27 | WORD biBitCount; //采用颜色位数,可以是1,2,4,8,16,24,新的可以是32 28 | DWORD biCompression; //压缩方式,可以是0,1,2,其中0表示不压缩 29 | DWORD biSizeImage; //实际位图数据占用的字节数 30 | LONG biXPelsPerMeter; //X方向分辨率 31 | LONG biYPelsPerMeter; //Y方向分辨率 32 | DWORD biClrUsed; //使用的颜色数,如果为0,则表示默认值(2^颜色位数) 33 | DWORD biClrImportant; //重要颜色数,如果为0,则表示所有颜色都是重要的 34 | } BITMAPINFOHEADER; 35 | 36 | //调色板Palette,当然,这里是对那些需要调色板的位图文件而言的。24位和32位是不需要调色板的。 37 | //(似乎是调色板结构体个数等于使用的颜色数。) 38 | typedef struct tagRGBQUAD { 39 | //public: 40 | BYTE rgbBlue; //该颜色的蓝色分量 41 | BYTE rgbGreen; //该颜色的绿色分量 42 | BYTE rgbRed; //该颜色的红色分量 43 | BYTE rgbReserved; //保留值 44 | } RGBQUAD; 45 | 46 | typedef struct PicNode { 47 | RGBQUAD *data; 48 | int width; 49 | int height; 50 | } PICNODE; 51 | 52 | void loadBitmap(PICNODE *pic, char pic_name[]); 53 | void freepic(PICNODE *pic); 54 | void set_icon_alpha(PICNODE *pic); 55 | #endif 56 | -------------------------------------------------------------------------------- /xv6/blank.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/blank.bmp -------------------------------------------------------------------------------- /xv6/bootasm.S: -------------------------------------------------------------------------------- 1 | #include "asm.h" 2 | #include "memlayout.h" 3 | #include "mmu.h" 4 | 5 | # Start the first CPU: switch to 32-bit protected mode, jump into C. 6 | # The BIOS loads this code from the first sector of the hard disk into 7 | # memory at physical address 0x7c00 and starts executing in real mode 8 | # with %cs=0 %ip=7c00. 9 | 10 | .code16 # Assemble for 16-bit mode 11 | .globl start 12 | start: 13 | cli # BIOS enabled interrupts; disable 14 | 15 | # Zero data segment registers DS, ES, and SS. 16 | xorw %ax,%ax # Set %ax to zero 17 | movw %ax,%ds # -> Data Segment 18 | movw %ax,%es # -> Extra Segment 19 | movw %ax,%ss # -> Stack Segment 20 | 21 | # Physical address line A20 is tied to zero so that the first PCs 22 | # with 2 MB would run software that assumed 1 MB. Undo that. 23 | seta20.1: 24 | inb $0x64,%al # Wait for not busy 25 | testb $0x2,%al 26 | jnz seta20.1 27 | 28 | movb $0xd1,%al # 0xd1 -> port 0x64 29 | outb %al,$0x64 30 | 31 | seta20.2: 32 | inb $0x64,%al # Wait for not busy 33 | testb $0x2,%al 34 | jnz seta20.2 35 | 36 | movb $0xdf,%al # 0xdf -> port 0x60 37 | outb %al,$0x60 38 | 39 | # Get VESA mode 40 | movw $0x1000, %di # %di: the address to save VESA mode info 41 | movw $0x4f01, %ax # %ax: 0x4f01 is to get VESA mode info 42 | movw $0x4114, %cx # %cx: 0x4114 mean 800*600(5:6:5) mode 43 | int $0x10 44 | 45 | # Set VESA mode 46 | movw $0x4f02, %ax # %ax: 0x4f02 is to set VESA mode info 47 | movw $0x4114, %bx # %bx: 0x4114 mean 800*600(5:6:5) mode 48 | int $0x10 49 | 50 | # Switch from real to protected mode. Use a bootstrap GDT that makes 51 | # virtual addresses map directly to physical addresses so that the 52 | # effective memory map doesn't change during the transition. 53 | lgdt gdtdesc 54 | movl %cr0, %eax 55 | orl $CR0_PE, %eax 56 | movl %eax, %cr0 57 | 58 | //PAGEBREAK! 59 | # Complete transition to 32-bit protected mode by using long jmp 60 | # to reload %cs and %eip. The segment descriptors are set up with no 61 | # translation, so that the mapping is still the identity mapping. 62 | ljmp $(SEG_KCODE<<3), $start32 63 | 64 | .code32 # Tell assembler to generate 32-bit code now. 65 | start32: 66 | # Set up the protected-mode data segment registers 67 | movw $(SEG_KDATA<<3), %ax # Our data segment selector 68 | movw %ax, %ds # -> DS: Data Segment 69 | movw %ax, %es # -> ES: Extra Segment 70 | movw %ax, %ss # -> SS: Stack Segment 71 | movw $0, %ax # Zero segments not ready for use 72 | movw %ax, %fs # -> FS 73 | movw %ax, %gs # -> GS 74 | 75 | # Set up the stack pointer and call into C. 76 | movl $start, %esp 77 | call bootmain 78 | 79 | # If bootmain returns (it shouldn't), trigger a Bochs 80 | # breakpoint if running under Bochs, then loop. 81 | movw $0x8a00, %ax # 0x8a00 -> port 0x8a00 82 | movw %ax, %dx 83 | outw %ax, %dx 84 | movw $0x8ae0, %ax # 0x8ae0 -> port 0x8a00 85 | outw %ax, %dx 86 | spin: 87 | jmp spin 88 | 89 | # Bootstrap GDT 90 | .p2align 2 # force 4 byte alignment 91 | gdt: 92 | SEG_NULLASM # null seg 93 | SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg 94 | SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg 95 | 96 | gdtdesc: 97 | .word (gdtdesc - gdt - 1) # sizeof(gdt) - 1 98 | .long gdt # address gdt 99 | 100 | -------------------------------------------------------------------------------- /xv6/bootmain.c: -------------------------------------------------------------------------------- 1 | // Boot loader. 2 | // 3 | // Part of the boot sector, along with bootasm.S, which calls bootmain(). 4 | // bootasm.S has put the processor into protected 32-bit mode. 5 | // bootmain() loads an ELF kernel image from the disk starting at 6 | // sector 1 and then jumps to the kernel entry routine. 7 | 8 | #include "types.h" 9 | #include "elf.h" 10 | #include "x86.h" 11 | #include "memlayout.h" 12 | 13 | #define SECTSIZE 512 14 | 15 | void readseg(uchar*, uint, uint); 16 | 17 | void 18 | bootmain(void) 19 | { 20 | struct elfhdr *elf; 21 | struct proghdr *ph, *eph; 22 | void (*entry)(void); 23 | uchar* pa; 24 | 25 | elf = (struct elfhdr*)0x10000; // scratch space 26 | 27 | // Read 1st page off disk 28 | readseg((uchar*)elf, 4096, 0); 29 | 30 | // Is this an ELF executable? 31 | if(elf->magic != ELF_MAGIC) 32 | return; // let bootasm.S handle error 33 | 34 | // Load each program segment (ignores ph flags). 35 | ph = (struct proghdr*)((uchar*)elf + elf->phoff); 36 | eph = ph + elf->phnum; 37 | for(; ph < eph; ph++){ 38 | pa = (uchar*)ph->paddr; 39 | readseg(pa, ph->filesz, ph->off); 40 | if(ph->memsz > ph->filesz) 41 | stosb(pa + ph->filesz, 0, ph->memsz - ph->filesz); 42 | } 43 | 44 | // Call the entry point from the ELF header. 45 | // Does not return! 46 | entry = (void(*)(void))(elf->entry); 47 | entry(); 48 | } 49 | 50 | void 51 | waitdisk(void) 52 | { 53 | // Wait for disk ready. 54 | while((inb(0x1F7) & 0xC0) != 0x40) 55 | ; 56 | } 57 | 58 | // Read a single sector at offset into dst. 59 | void 60 | readsect(void *dst, uint offset) 61 | { 62 | // Issue command. 63 | waitdisk(); 64 | outb(0x1F2, 1); // count = 1 65 | outb(0x1F3, offset); 66 | outb(0x1F4, offset >> 8); 67 | outb(0x1F5, offset >> 16); 68 | outb(0x1F6, (offset >> 24) | 0xE0); 69 | outb(0x1F7, 0x20); // cmd 0x20 - read sectors 70 | 71 | // Read data. 72 | waitdisk(); 73 | insl(0x1F0, dst, SECTSIZE/4); 74 | } 75 | 76 | // Read 'count' bytes at 'offset' from kernel into physical address 'pa'. 77 | // Might copy more than asked. 78 | void 79 | readseg(uchar* pa, uint count, uint offset) 80 | { 81 | uchar* epa; 82 | 83 | epa = pa + count; 84 | 85 | // Round down to sector boundary. 86 | pa -= offset % SECTSIZE; 87 | 88 | // Translate from bytes to sectors; kernel starts at sector 1. 89 | offset = (offset / SECTSIZE) + 1; 90 | 91 | // If this is too slow, we could read lots of sectors at a time. 92 | // We'd write more to memory than asked, but it doesn't matter -- 93 | // we load in increasing order. 94 | for(; pa < epa; pa += SECTSIZE, offset++) 95 | readsect(pa, offset); 96 | } 97 | -------------------------------------------------------------------------------- /xv6/buf.h: -------------------------------------------------------------------------------- 1 | struct buf { 2 | int flags; 3 | uint dev; 4 | uint sector; 5 | struct buf *prev; // LRU cache list 6 | struct buf *next; 7 | struct buf *qnext; // disk queue 8 | uchar data[512]; 9 | }; 10 | #define B_BUSY 0x1 // buffer is locked by some process 11 | #define B_VALID 0x2 // buffer has been read from disk 12 | #define B_DIRTY 0x4 // buffer needs to be written to disk 13 | 14 | -------------------------------------------------------------------------------- /xv6/cal.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | #include "fcntl.h" 5 | 6 | 7 | #define MAXCOUNT 100 8 | #define MAXNUM 10 9 | 10 | 11 | int chars_to_int(char* src) 12 | { 13 | char* r = (char*)malloc(10 * sizeof(char)); 14 | int ret = 0; 15 | int j; 16 | if (src[0] == '-') 17 | { 18 | for (j = 0; j < 9; j++) 19 | { 20 | r[j] = src[j + 1]; 21 | } 22 | return -chars_to_int(r); 23 | } 24 | for (j = 0; j < strlen(src); j++) 25 | { 26 | ret *= 10; 27 | ret += src[j] - '0'; 28 | } 29 | return ret; 30 | } 31 | 32 | char* int_to_chars(char* ret, const int n){ 33 | int i = 0, temp = n, j = 0; 34 | while(temp){ 35 | temp /= 10; 36 | i++; 37 | } 38 | temp = n; 39 | for(j = i - 1; j >= 0; j--){ 40 | ret[j] = temp % 10 + '0'; 41 | temp /= 10; 42 | } 43 | ret[i] = 0; 44 | return ret; 45 | } 46 | 47 | char** split(char* src) 48 | { 49 | char** ret = (char**)malloc(MAXCOUNT*sizeof(char*)); 50 | int i, j, k; 51 | char* c; 52 | for (i = 0; i < MAXCOUNT; i++) 53 | { 54 | ret[i] = (char*)malloc(MAXNUM*sizeof(char)); 55 | for (j = 0; j < MAXNUM; j++) 56 | ret[i][j] = 0; 57 | } 58 | i = 0; 59 | j = 0; 60 | k = 0; 61 | while (i < strlen(src)) 62 | { 63 | if (src[i] >= '0'&&src[i] <= '9') 64 | { 65 | ret[j][k] = src[i]; 66 | k++; 67 | i++; 68 | } 69 | else 70 | { 71 | if (k) j++; 72 | ret[j][0] = src[i]; 73 | j++; 74 | i++; 75 | k = 0; 76 | } 77 | } 78 | if (ret[0][0] == '-') 79 | { 80 | c = ret[99]; 81 | for (i = 98; i >= 0; i--) 82 | { 83 | ret[i + 1] = ret[i]; 84 | } 85 | ret[0] = c; 86 | ret[0][0] = '0'; 87 | } 88 | return ret; 89 | } 90 | 91 | char precede(char x, char y){ 92 | int i=0, j=0; 93 | 94 | switch (x){ 95 | case '+':i = 3; break; 96 | case '-':i = 3; break; 97 | case '*':i = 5; break; 98 | case '/':i = 5; break; 99 | case '(':i = 1; break; 100 | case ')':i = 8; break; 101 | case '\0':i = 0; break; 102 | } 103 | switch (y){ 104 | case '+':j = 3; break; 105 | case '-':j = 3; break; 106 | case '*':j = 5; break; 107 | case '/':j = 6; break; 108 | case '(':j = 1; break; 109 | case ')':j = 8; break; 110 | case '\0':j = 0; break; 111 | } 112 | if (i>j) 113 | return '>'; 114 | else 115 | if (i= 0) 199 | ret = int_to_chars(ret, res); 200 | else 201 | { 202 | r = int_to_chars(r, -res); 203 | ret[0] = '-'; 204 | ret[1] = 0; 205 | for (i = 0; i < 9; i++) 206 | { 207 | ret[i+1] = r[i]; 208 | } 209 | } 210 | 211 | return ret; 212 | } 213 | 214 | char* caln(char** src) 215 | { 216 | int i; 217 | int m = -1; 218 | int a1 = -1; 219 | int a2 = -1; 220 | for (i = 0; i < MAXCOUNT; i++) 221 | { 222 | if ((src[i][0] >= '0' && src[i][0] <= '9' )|| (src[i][0] == '-'&&src[i][1])) 223 | { 224 | a1 = a2; 225 | a2 = i; 226 | } 227 | if (src[i][0] == '+' || (src[i][0] == '-'&&src[i][1]==0) || src[i][0] == '*' || src[i][0] == '/') 228 | { 229 | m = i; 230 | break; 231 | } 232 | } 233 | if (m == -1) 234 | { 235 | return src[a2]; 236 | } 237 | src[a1] = cal3(src[a1], src[a2], src[m]); 238 | src[a2][0] = src[m][0] = 0; 239 | return caln(src); 240 | } 241 | 242 | 243 | int cal(char* src) 244 | { 245 | char* res = caln(toRPN(split(src))); 246 | printf(2, "The answer is: %s\n", res); 247 | return chars_to_int(res); 248 | } 249 | 250 | int 251 | main(int argc, char *argv[]) 252 | { 253 | if(argc != 2){ 254 | printf(2, "Usage: calculate a expression...\n"); 255 | chdir("/"); 256 | exit(); 257 | } 258 | 259 | if(argc == 2){ 260 | cal(argv[1]); 261 | } 262 | chdir("/"); 263 | exit(); 264 | } 265 | -------------------------------------------------------------------------------- /xv6/cat.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | char buf[512]; 6 | 7 | void 8 | cat(int fd) 9 | { 10 | int n; 11 | 12 | while((n = read(fd, buf, sizeof(buf))) > 0) 13 | write(1, buf, n); 14 | if(n < 0){ 15 | printf(1, "cat: read error\n"); 16 | exit(); 17 | } 18 | } 19 | 20 | int 21 | main(int argc, char *argv[]) 22 | { 23 | int fd, i; 24 | 25 | if(argc <= 1){ 26 | cat(0); 27 | exit(); 28 | } 29 | 30 | for(i = 1; i < argc; i++){ 31 | if((fd = open(argv[i], 0)) < 0){ 32 | printf(1, "cat: cannot open %s\n", argv[i]); 33 | exit(); 34 | } 35 | cat(fd); 36 | close(fd); 37 | } 38 | exit(); 39 | } 40 | -------------------------------------------------------------------------------- /xv6/clickable.c: -------------------------------------------------------------------------------- 1 | #include "clickable.h" 2 | #include "context.h" 3 | #include "message.h" 4 | #include "types.h" 5 | #include "user.h" 6 | #include "finder.h" 7 | Point initPoint(int x, int y) 8 | { 9 | Point p; 10 | p.x = x; 11 | p.y = y; 12 | return p; 13 | } 14 | 15 | Rect initRect(int x, int y, int w, int h) 16 | { 17 | Rect r; 18 | r.start = initPoint(x, y); 19 | r.width = w; 20 | r.height = h; 21 | return r; 22 | } 23 | 24 | int isIn(Point p, Rect r) 25 | { 26 | return (p.x >= r.start.x) && (p.x < r.start.x+r.width) 27 | && (p.y >= r.start.y) && (p.y < r.start.y+r.height); 28 | } 29 | 30 | ClickableManager initClickManager(struct Context c) 31 | { 32 | ClickableManager cm; 33 | cm.left_click = 0; 34 | cm.double_click = 0; 35 | cm.right_click = 0; 36 | cm.wndWidth = c.width; 37 | cm.wndHeight = c.height; 38 | return cm; 39 | } 40 | 41 | void createClickable(ClickableManager *c, Rect r, int MsgType, Handler h) 42 | { 43 | switch (MsgType) 44 | { 45 | case MSG_DOUBLECLICK: 46 | addClickable(&c->double_click, r, h); 47 | break; 48 | case MSG_LPRESS: 49 | addClickable(&c->left_click, r, h); 50 | break; 51 | case MSG_RPRESS: 52 | addClickable(&c->right_click, r, h); 53 | break; 54 | default: 55 | printf(0, "向clickable传递了非鼠标点击事件!"); 56 | break; 57 | } 58 | } 59 | 60 | void addClickable(Clickable **head, Rect r, Handler h) 61 | { 62 | //printf(0, "adding clickable\n"); 63 | Clickable *c = (Clickable *)malloc(sizeof(Clickable)); 64 | c->area = r; 65 | c->handler = h; 66 | c->next = *head; 67 | *head = c; 68 | } 69 | 70 | void deleteClickable(Clickable **head, Rect region) 71 | { 72 | Clickable *prev, *cur, *temp; 73 | prev = cur = *head; 74 | while (cur != 0) 75 | { 76 | if (isIn(cur->area.start, region)) 77 | { 78 | //如果当前指针指向头部 79 | if (cur == *head) 80 | { 81 | //删除头节点 82 | temp = *head; 83 | *head = cur->next; 84 | cur = prev = *head; 85 | free(temp); 86 | } 87 | else 88 | { 89 | //删除当前节点 90 | prev->next = cur->next; 91 | temp = cur; 92 | cur = cur->next; 93 | free(temp); 94 | } 95 | } 96 | else 97 | { 98 | //如果当前节点是头节点, 99 | if (cur == *head) 100 | { 101 | cur = cur->next; 102 | } 103 | else 104 | { 105 | cur = cur->next; 106 | prev = prev->next; 107 | } 108 | } 109 | } 110 | } 111 | 112 | int executeHandler(Clickable *head, Point click) 113 | { 114 | Clickable *cur = head; 115 | while (cur != 0) 116 | { 117 | if (isIn(click, cur->area)) 118 | { 119 | renaming = 0; 120 | isSearching = 0; 121 | cur->handler(click); 122 | return 1; 123 | } 124 | cur = cur->next; 125 | } 126 | isSearching = 0; 127 | if (renaming == 1){ 128 | renaming = 0; 129 | return 1; 130 | } 131 | printf(0, "execute: none!\n"); 132 | return 0; 133 | } 134 | 135 | void printClickable(Clickable *c) 136 | { 137 | printf(0, "(%d, %d, %d, %d)\n", c->area.start.x, c->area.start.y, c->area.width, c->area.height); 138 | } 139 | 140 | void printClickableList(Clickable *head) 141 | { 142 | Clickable *cur = head; 143 | printf(0, "Clickable List:\n"); 144 | while(cur != 0) 145 | { 146 | printClickable(cur); 147 | cur = cur->next; 148 | } 149 | printf(0, "\n"); 150 | } 151 | 152 | void testHanler(struct Point p) 153 | { 154 | printf(0, "execute: (%d, %d)!\n", p.x, p.y); 155 | } 156 | void testClickable(struct Context c) 157 | { 158 | ClickableManager cm = initClickManager(c); 159 | 160 | Rect r1 = initRect(5,5,20,20); 161 | Rect r2 = initRect(20,20,20,20); 162 | Rect r3 = initRect(50,50,15,15); 163 | Rect r4 = initRect(0,0,30,30); 164 | Point p1 = initPoint(23, 23); 165 | Point p2 = initPoint(70, 70); 166 | createClickable(&cm, r1, MSG_LPRESS, &testHanler); 167 | printf(0, "left_click: %d\n", cm.left_click); 168 | createClickable(&cm, r2, MSG_LPRESS, &testHanler); 169 | printf(0, "left_click: %d\n", cm.left_click); 170 | createClickable(&cm, r3, MSG_LPRESS, &testHanler); 171 | printf(0, "left_click: %d\n", cm.left_click); 172 | printClickableList(cm.left_click); 173 | executeHandler(cm.left_click, p1); 174 | executeHandler(cm.left_click, p2); 175 | deleteClickable(&cm.left_click, r4); 176 | printClickableList(cm.left_click); 177 | } 178 | -------------------------------------------------------------------------------- /xv6/clickable.h: -------------------------------------------------------------------------------- 1 | #ifndef CLICKABLE_H 2 | #define CLICKABLE_H 3 | 4 | typedef struct Point 5 | { 6 | int x; 7 | int y; 8 | } Point; 9 | 10 | Point initPoint(int x, int y); 11 | 12 | typedef struct Rect 13 | { 14 | Point start; 15 | int width; 16 | int height; 17 | } Rect; 18 | 19 | Rect initRect(int x, int y, int w, int h); 20 | int isIn(Point p, Rect r); 21 | typedef void(*Handler)(Point); 22 | typedef struct Clickable 23 | { 24 | Rect area; 25 | Handler handler; 26 | struct Clickable *next; 27 | } Clickable; 28 | 29 | typedef struct ClickableManager 30 | { 31 | Clickable *left_click; 32 | Clickable *double_click; 33 | Clickable *right_click; 34 | int wndWidth; 35 | int wndHeight; 36 | } ClickableManager; 37 | 38 | struct Context; 39 | ClickableManager initClickManager(struct Context c); 40 | 41 | //MsgType 单击,双击还是右键 42 | void createClickable(ClickableManager *c, Rect r, int MsgType, Handler h); 43 | //添加一个区域为r,处理事件为h的clickable,添加到链表头部 44 | void addClickable(Clickable **head, Rect r, Handler h); 45 | //删除起始坐标在region内部的所有Clickable 46 | void deleteClickable(Clickable **head, Rect region); 47 | //执行点击坐标在area内部的clickable函数 48 | int executeHandler(Clickable *head, Point click); 49 | void testClickable(struct Context c); 50 | #endif 51 | -------------------------------------------------------------------------------- /xv6/close.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/close.bmp -------------------------------------------------------------------------------- /xv6/common.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/common.h -------------------------------------------------------------------------------- /xv6/context.c: -------------------------------------------------------------------------------- 1 | #include "context.h" 2 | #include "types.h" 3 | #include "stat.h" 4 | #include "user.h" 5 | #include "drawingAPI.h" 6 | 7 | int init_context(struct Context* context_ptr, int width, int height) 8 | { 9 | context_ptr->width = width; 10 | context_ptr->height = height; 11 | context_ptr->addr = (unsigned short*)malloc(sizeof(unsigned short) * width * height); 12 | memset(context_ptr->addr, 0, sizeof(unsigned short) * width * height); 13 | initializeASCII(); 14 | initializeGBK(); 15 | return createWindow(0, 0, width, height); 16 | } 17 | 18 | void free_context(struct Context* context_ptr, int winid) 19 | { 20 | free(context_ptr->addr); 21 | freeASCII(); 22 | freeGBK(); 23 | destroyWindow(winid); 24 | } 25 | -------------------------------------------------------------------------------- /xv6/context.h: -------------------------------------------------------------------------------- 1 | #ifndef CONTEXT_H 2 | #define CONTEXT_H 3 | 4 | struct Clickable; 5 | typedef struct Context 6 | { 7 | unsigned short *addr; 8 | int width; 9 | int height; 10 | } Context; 11 | 12 | //context 函数接口 13 | int init_context(struct Context* context_ptr, int width, int height); 14 | void free_context(struct Context* context_ptr, int winid); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /xv6/copy.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/copy.bmp -------------------------------------------------------------------------------- /xv6/cp.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | #include "fcntl.h" 5 | #include "fs.h" 6 | 7 | #define BUF_SIZE 256 8 | 9 | void ls(char *path); 10 | char* fmtname(char *path); 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | //判断参数 15 | if (argc !=3) 16 | { 17 | printf(1, "please input the command as [cp src_file dest_file]\n"); 18 | exit(); 19 | } 20 | 21 | //打开源文件 22 | int fd_src = open(argv[1], O_RDONLY); 23 | if (fd_src == -1) 24 | { 25 | printf(1, "open source file failed\n"); 26 | exit(); 27 | } 28 | 29 | //判断源文件状态是否为文件夹 30 | struct stat st; 31 | fstat(fd_src, &st); 32 | if (st.type == T_DIR) 33 | { 34 | printf(1, "source file is a directory, the files in that directory is:\n"); 35 | ls(argv[1]); 36 | printf(1, "the program can't open the file in that directory after list them.\n"); 37 | printf(1, "So, I'm sorry that you have to copy them one by one.\n"); 38 | exit(); 39 | } 40 | 41 | //判断第二个参数是不是以"/"结尾,如果是,则补全路径 42 | char com[128] = {}; 43 | strcpy(com, argv[2]); 44 | int len1 = strlen(argv[1]); 45 | int len2 = strlen(argv[2]); 46 | if (argv[2][len2-1] == '/') 47 | { 48 | //找到argv[1]中的文件名 49 | int i = len1 - 1; 50 | for (; i >= 0; i--) 51 | if (argv[1][i] == '/') 52 | break; 53 | i++; 54 | strcpy(&com[len2], &argv[1][i]); 55 | } 56 | 57 | //打开目标文件 58 | int fd_dest = open(com, O_WRONLY|O_CREATE); 59 | if (fd_dest == -1) 60 | { 61 | printf(1, "create dest file failed\n"); 62 | exit(); 63 | } 64 | 65 | //复制文件 66 | char buf[BUF_SIZE] = {}; 67 | int len = 0; 68 | while((len = read(fd_src, buf, BUF_SIZE)) > 0) 69 | write(fd_dest, buf, len); 70 | 71 | //关闭文件和程序 72 | close(fd_src); 73 | close(fd_dest); 74 | exit(); 75 | } 76 | 77 | char* fmtname(char *path) 78 | { 79 | static char buf[DIRSIZ+1]; 80 | char *p; 81 | 82 | // Find first character after last slash. 83 | for(p=path+strlen(path); p >= path && *p != '/'; p--) 84 | ; 85 | p++; 86 | 87 | // Return blank-padded name. 88 | if(strlen(p) >= DIRSIZ) 89 | return p; 90 | memmove(buf, p, strlen(p)); 91 | memset(buf+strlen(p), ' ', DIRSIZ-strlen(p)); 92 | return buf; 93 | } 94 | 95 | void ls(char *path) 96 | { 97 | char buf[512], *p; 98 | int fd; 99 | struct dirent de; 100 | struct stat st; 101 | 102 | if((fd = open(path, 0)) < 0) 103 | { 104 | printf(2, "cannot open %s\n", path); 105 | return; 106 | } 107 | 108 | if(fstat(fd, &st) < 0) 109 | { 110 | printf(2, "cannot stat %s\n", path); 111 | close(fd); 112 | return; 113 | } 114 | 115 | switch(st.type) 116 | { 117 | case T_FILE: 118 | printf(1, "name = %s, type = file, size = %d\n", fmtname(path), st.size); 119 | break; 120 | 121 | case T_DIR: 122 | if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf) 123 | { 124 | printf(1, "path too long\n"); 125 | break; 126 | } 127 | strcpy(buf, path); 128 | p = buf+strlen(buf); 129 | *p++ = '/'; 130 | 131 | while(read(fd, &de, sizeof(de)) == sizeof(de)) 132 | { 133 | if(de.inum == 0) 134 | continue; 135 | memmove(p, de.name, DIRSIZ); 136 | p[DIRSIZ] = 0; 137 | if(stat(buf, &st) < 0) 138 | { 139 | printf(1, "cannot stat %s\n", buf); 140 | continue; 141 | } 142 | printf(1, "name = %s, type = directory, size = %d\n", fmtname(buf), st.size); 143 | } 144 | break; 145 | } 146 | close(fd); 147 | } 148 | -------------------------------------------------------------------------------- /xv6/createfile.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/createfile.bmp -------------------------------------------------------------------------------- /xv6/createfolder.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/createfolder.bmp -------------------------------------------------------------------------------- /xv6/cty.txt: -------------------------------------------------------------------------------- 1 | chen tong yu dddddddddddddddddddddassssssssssssssssssssssssssssssssssddddssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd 2 | -------------------------------------------------------------------------------- /xv6/cut.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/cut.bmp -------------------------------------------------------------------------------- /xv6/cuth: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | $| = 1; 4 | 5 | sub writefile($@){ 6 | my ($file, @lines) = @_; 7 | 8 | sleep(1); 9 | open(F, ">$file") || die "open >$file: $!"; 10 | print F @lines; 11 | close(F); 12 | } 13 | 14 | # Cut out #include lines that don't contribute anything. 15 | for($i=0; $i<@ARGV; $i++){ 16 | $file = $ARGV[$i]; 17 | if(!open(F, $file)){ 18 | print STDERR "open $file: $!\n"; 19 | next; 20 | } 21 | @lines = ; 22 | close(F); 23 | 24 | $obj = "$file.o"; 25 | $obj =~ s/\.c\.o$/.o/; 26 | system("touch $file"); 27 | 28 | if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){ 29 | print STDERR "make $obj failed: $rv\n"; 30 | next; 31 | } 32 | 33 | system("cp $file =$file"); 34 | for($j=@lines-1; $j>=0; $j--){ 35 | if($lines[$j] =~ /^#include/){ 36 | $old = $lines[$j]; 37 | $lines[$j] = "/* CUT-H */\n"; 38 | writefile($file, @lines); 39 | if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){ 40 | $lines[$j] = $old; 41 | }else{ 42 | print STDERR "$file $old"; 43 | } 44 | } 45 | } 46 | writefile($file, grep {!/CUT-H/} @lines); 47 | system("rm =$file"); 48 | } 49 | -------------------------------------------------------------------------------- /xv6/date.h: -------------------------------------------------------------------------------- 1 | struct rtcdate { 2 | uint second; 3 | uint minute; 4 | uint hour; 5 | uint day; 6 | uint month; 7 | uint year; 8 | }; 9 | -------------------------------------------------------------------------------- /xv6/decode.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "user.h" 3 | int main() 4 | { 5 | while (1) 6 | wavdecode(); 7 | exit(); 8 | } 9 | -------------------------------------------------------------------------------- /xv6/decode.h: -------------------------------------------------------------------------------- 1 | #ifndef _DECODE_H_ 2 | #define _DECODE_H_ 3 | 4 | #include "common.h" 5 | 6 | void decode_info(Bit_stream_struc*, struct frame_params*); 7 | void III_get_side_info(Bit_stream_struc *bs, struct III_side_info_t *si, struct frame_params *fr_ps); 8 | void III_get_scale_factors(III_scalefac_t *scalefac, struct III_side_info_t *si, int gr, int ch, struct frame_params *fr_ps); 9 | 10 | void initialize_huffman(); 11 | void III_hufman_decode(long int is[SBLIMIT][SSLIMIT], struct III_side_info_t *si, int ch, int gr, int part2_start, struct frame_params *fr_ps); 12 | 13 | void III_dequantize_sample(long int[SBLIMIT][SSLIMIT], double [SBLIMIT][SSLIMIT], III_scalefac_t *, struct gr_info_s *, int, struct frame_params *); 14 | void III_reorder(double xr[SBLIMIT][SSLIMIT], double ro[SBLIMIT][SSLIMIT], struct gr_info_s *gr_info, struct frame_params *fr_ps); 15 | void III_stereo(double xr[2][SBLIMIT][SSLIMIT], double lr[2][SBLIMIT][SSLIMIT], III_scalefac_t *scalefac, struct gr_info_s *gr_info, struct frame_params *fr_ps); 16 | void III_antialias(double xr[SBLIMIT][SSLIMIT], double hybridIn[SBLIMIT][SSLIMIT], struct gr_info_s *gr_info, struct frame_params *fr_ps); 17 | 18 | void inv_mdct(double in[18], double out[36], int block_type); 19 | void III_hybrid(double fsIn[SSLIMIT], double tsOut[SSLIMIT], int sb, int ch, struct gr_info_s *gr_info, struct frame_params *fr_ps); 20 | 21 | void create_syn_filter(double filter[64][SBLIMIT]); 22 | void read_syn_window(double window[HAN_SIZE]); 23 | int SubBandSynthesis (double *bandPtr, int channel, short *samples); 24 | 25 | void out_fifo(short pcm_sample[2][SSLIMIT][SBLIMIT], int num, struct frame_params *fr_ps, unsigned long *psampFrames); 26 | void buffer_CRC(Bit_stream_struc *bs, unsigned int *old_crc); 27 | int main_data_slots(struct frame_params fr_ps); 28 | 29 | extern double gb_window[HAN_SIZE]; 30 | #endif //_DECODE_H_ 31 | -------------------------------------------------------------------------------- /xv6/decodemp3.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/decodemp3.c -------------------------------------------------------------------------------- /xv6/desktop.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | #include "context.h" 5 | #include "drawingAPI.h" 6 | #include "bitmap.h" 7 | #include "message.h" 8 | #include "clickable.h" 9 | 10 | ICON iconlist[] = { 11 | {"music.bmp", 175, 400}, 12 | {"finder.bmp", 300, 400}, 13 | {"terminal.bmp", 425, 400}, 14 | //{"setting.bmp", 550, 400} 15 | }; 16 | 17 | void shellinit(Point point) 18 | { 19 | int pid; 20 | char* shell_argv[] = { "shell_gui", 0 }; 21 | 22 | printf(1, "init shell: starting shell\n"); 23 | pid = fork(); 24 | if (pid < 0) 25 | { 26 | printf(1, "init shell: fork failed\n"); 27 | exit(); 28 | } 29 | if (pid == 0) 30 | { 31 | exec("shell_gui", shell_argv); 32 | printf(1, "init shell: exec shell failed\n"); 33 | exit(); 34 | } 35 | // return pid; 36 | } 37 | 38 | void finderinit(Point point) 39 | { 40 | int pid; 41 | char* finder_argv[] = { "finder", 0 }; 42 | 43 | printf(1, "init finder: starting finder\n"); 44 | pid = fork(); 45 | if (pid < 0) 46 | { 47 | printf(1, "init finder: fork failed\n"); 48 | exit(); 49 | } 50 | if (pid == 0) 51 | { 52 | exec("finder", finder_argv); 53 | printf(1, "init finder: exec finder failed\n"); 54 | exit(); 55 | } 56 | // return pid; 57 | } 58 | 59 | void playmusic(Point point) 60 | { 61 | int pid; 62 | char* argv[] = { "playmusic", "qian.wav" , "test.wav", "in.mp3"}; 63 | printf(0, "init player: starting player \n"); 64 | pid = fork(); 65 | if (pid < 0) 66 | { 67 | printf(1, "init player: fork failed\n"); 68 | exit(); 69 | } 70 | if (pid == 0) 71 | { 72 | exec("playmusic", argv); 73 | printf(1, "init player: exec play failed\n"); 74 | exit(); 75 | } 76 | } 77 | 78 | int main(int argc, char *argv[]) 79 | { 80 | int winid; 81 | struct Msg msg; 82 | struct Context context; 83 | //int shell_pid; 84 | //int finder_pid; 85 | short isRun = 1; 86 | // short isInit = 1; 87 | ClickableManager manager; 88 | 89 | winid = init_context(&context, 800, 600); 90 | fill_rect(context, 0, 0, context.width, context.height, 0xffff); 91 | // puts_str(context, "desktop: welcome", 0x0, 0, 0); 92 | 93 | PICNODE pic1, pic2, pic3, background; 94 | loadBitmap(&pic1, "music.bmp"); 95 | loadBitmap(&pic2, "setting.bmp"); 96 | loadBitmap(&pic3, "notes.bmp"); 97 | //loadBitmap(&background, "bg.bmp"); 98 | set_icon_alpha(&pic1); 99 | set_icon_alpha(&pic2); 100 | set_icon_alpha(&pic3); 101 | // set_icon_alpha(&pic4); 102 | // 103 | //fill_rect(context, 160, 400, 500, 150, 0x0101); 104 | // //loadBitmap(&background, "bg.bmp"); 105 | 106 | draw_picture(context, background, 0, 0); 107 | draw_picture(context, pic1, 225, 450); 108 | draw_picture(context, pic2, 363, 450); 109 | draw_picture(context, pic3, 500, 450); 110 | //draw_iconlist(context, iconlist, sizeof(iconlist) / sizeof(ICON)); 111 | 112 | manager = initClickManager(context); 113 | createClickable(&manager, initRect(225, 450, 75, 75), MSG_DOUBLECLICK, playmusic); 114 | createClickable(&manager, initRect(367, 450, 75, 75), MSG_DOUBLECLICK, shellinit); 115 | createClickable(&manager, initRect(500, 450, 75, 75), MSG_DOUBLECLICK, finderinit); 116 | 117 | while(isRun) 118 | { 119 | getMsg(&msg); 120 | switch(msg.msg_type) 121 | { 122 | case MSG_UPDATE: 123 | printf(1, "msg_detail %d\n", msg.msg_detail); 124 | updateWindow(winid, context.addr, msg.msg_detail); 125 | //printf(0, "desktop"); 126 | /*if (isInit) 127 | { 128 | finderinit((Point){0, 0}); 129 | //finderinit((Point){0, 0}); 130 | //shell_pid = shellinit((Point){context.width / 2, context.height / 2}); 131 | //shellinit((Point){context.width / 2, context.height / 2}); 132 | isInit = 0; 133 | }*/ 134 | break; 135 | case MSG_PARTIAL_UPDATE: 136 | updatePartialWindow(winid, context.addr, msg.concrete_msg.msg_partial_update.x1, msg.concrete_msg.msg_partial_update.y1, msg.concrete_msg.msg_partial_update.x2, msg.concrete_msg.msg_partial_update.y2); 137 | break; 138 | case MSG_DOUBLECLICK: 139 | executeHandler(manager.double_click, initPoint(msg.concrete_msg.msg_mouse.x, msg.concrete_msg.msg_mouse.y)); 140 | break; 141 | default: 142 | break; 143 | } 144 | } 145 | 146 | //int windowId; 147 | //int result; 148 | 149 | //windowId = createWindow(0, 0, 800, 600); 150 | //printf(0, "windowId: %d\n", windowId); 151 | 152 | 153 | //result = updateWindow(windowId, context.addr); 154 | //printf(0, "updateResult: %d\n", result); 155 | 156 | free_context(&context, winid); 157 | exit(); 158 | } 159 | -------------------------------------------------------------------------------- /xv6/down.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/down.bmp -------------------------------------------------------------------------------- /xv6/drawingAPI.h: -------------------------------------------------------------------------------- 1 | #ifndef DRAWINGAPI_H 2 | #define DRAWINGAPI_H 3 | 4 | #define HANKAKU "hankaku.txt" 5 | #define ASCII_NUM 256 6 | #define ASCII_WIDTH 8 7 | #define ASCII_HEIGHT 16 8 | #define ACCII_SIZE 128 9 | #define HZK16 "HZK16.fnt" 10 | 11 | #include "bitmap.h" 12 | 13 | struct File_Node 14 | { 15 | unsigned char * buf; 16 | int size; 17 | }; 18 | struct Context; 19 | //struct PicNode; 20 | typedef struct Icon { 21 | char name[32]; 22 | int position_x; 23 | int position_y; 24 | PICNODE pic; 25 | } ICON; 26 | 27 | void initializeASCII(); 28 | void initializeGBK(); 29 | void freeASCII(); 30 | void freeGBK(); 31 | void draw_point(struct Context c, unsigned int x, unsigned int y, unsigned short color); 32 | void fill_rect(struct Context c, unsigned int bx, unsigned int by, unsigned int width, unsigned int height, unsigned short color); 33 | void puts_str(struct Context c, char *str, unsigned short colorNum, int x, int y); 34 | void draw_picture(Context c, struct PicNode pic, int x, int y); 35 | void draw_line(Context c, int x0, int y0, int x1, int y1, unsigned short color); 36 | void draw_window(Context c, char *title); 37 | void load_iconlist(ICON* iconlist, int len); 38 | void draw_iconlist(Context c, ICON* iconlist, int len); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /xv6/echo.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char *argv[]) 7 | { 8 | int i; 9 | 10 | for(i = 1; i < argc; i++) 11 | printf(1, "%s%s", argv[i], i+1 < argc ? " " : "\n"); 12 | exit(); 13 | } 14 | -------------------------------------------------------------------------------- /xv6/elf.h: -------------------------------------------------------------------------------- 1 | // Format of an ELF executable file 2 | 3 | #define ELF_MAGIC 0x464C457FU // "\x7FELF" in little endian 4 | 5 | // File header 6 | struct elfhdr { 7 | uint magic; // must equal ELF_MAGIC 8 | uchar elf[12]; 9 | ushort type; 10 | ushort machine; 11 | uint version; 12 | uint entry; 13 | uint phoff; 14 | uint shoff; 15 | uint flags; 16 | ushort ehsize; 17 | ushort phentsize; 18 | ushort phnum; 19 | ushort shentsize; 20 | ushort shnum; 21 | ushort shstrndx; 22 | }; 23 | 24 | // Program section header 25 | struct proghdr { 26 | uint type; 27 | uint off; 28 | uint vaddr; 29 | uint paddr; 30 | uint filesz; 31 | uint memsz; 32 | uint flags; 33 | uint align; 34 | }; 35 | 36 | // Values for Proghdr type 37 | #define ELF_PROG_LOAD 1 38 | 39 | // Flag bits for Proghdr flags 40 | #define ELF_PROG_FLAG_EXEC 1 41 | #define ELF_PROG_FLAG_WRITE 2 42 | #define ELF_PROG_FLAG_READ 4 43 | -------------------------------------------------------------------------------- /xv6/entry.S: -------------------------------------------------------------------------------- 1 | # Multiboot header, for multiboot boot loaders like GNU Grub. 2 | # http://www.gnu.org/software/grub/manual/multiboot/multiboot.html 3 | # 4 | # Using GRUB 2, you can boot xv6 from a file stored in a 5 | # Linux file system by copying kernel or kernelmemfs to /boot 6 | # and then adding this menu entry: 7 | # 8 | # menuentry "xv6" { 9 | # insmod ext2 10 | # set root='(hd0,msdos1)' 11 | # set kernel='/boot/kernel' 12 | # echo "Loading ${kernel}..." 13 | # multiboot ${kernel} ${kernel} 14 | # boot 15 | # } 16 | 17 | #include "asm.h" 18 | #include "memlayout.h" 19 | #include "mmu.h" 20 | #include "param.h" 21 | 22 | # Multiboot header. Data to direct multiboot loader. 23 | .p2align 2 24 | .text 25 | .globl multiboot_header 26 | multiboot_header: 27 | #define magic 0x1badb002 28 | #define flags 0 29 | .long magic 30 | .long flags 31 | .long (-magic-flags) 32 | 33 | # By convention, the _start symbol specifies the ELF entry point. 34 | # Since we haven't set up virtual memory yet, our entry point is 35 | # the physical address of 'entry'. 36 | .globl _start 37 | _start = V2P_WO(entry) 38 | 39 | # Entering xv6 on boot processor, with paging off. 40 | .globl entry 41 | entry: 42 | # Turn on page size extension for 4Mbyte pages 43 | movl %cr4, %eax 44 | orl $(CR4_PSE), %eax 45 | movl %eax, %cr4 46 | # Set page directory 47 | movl $(V2P_WO(entrypgdir)), %eax 48 | movl %eax, %cr3 49 | # Turn on paging. 50 | movl %cr0, %eax 51 | orl $(CR0_PG|CR0_WP), %eax 52 | movl %eax, %cr0 53 | 54 | # Set up the stack pointer. 55 | movl $(stack + KSTACKSIZE), %esp 56 | 57 | # Jump to main(), and switch to executing at 58 | # high addresses. The indirect call is needed because 59 | # the assembler produces a PC-relative instruction 60 | # for a direct jump. 61 | mov $main, %eax 62 | jmp *%eax 63 | 64 | .comm stack, KSTACKSIZE 65 | -------------------------------------------------------------------------------- /xv6/entryother.S: -------------------------------------------------------------------------------- 1 | #include "asm.h" 2 | #include "memlayout.h" 3 | #include "mmu.h" 4 | 5 | # Each non-boot CPU ("AP") is started up in response to a STARTUP 6 | # IPI from the boot CPU. Section B.4.2 of the Multi-Processor 7 | # Specification says that the AP will start in real mode with CS:IP 8 | # set to XY00:0000, where XY is an 8-bit value sent with the 9 | # STARTUP. Thus this code must start at a 4096-byte boundary. 10 | # 11 | # Because this code sets DS to zero, it must sit 12 | # at an address in the low 2^16 bytes. 13 | # 14 | # Startothers (in main.c) sends the STARTUPs one at a time. 15 | # It copies this code (start) at 0x7000. It puts the address of 16 | # a newly allocated per-core stack in start-4,the address of the 17 | # place to jump to (mpenter) in start-8, and the physical address 18 | # of entrypgdir in start-12. 19 | # 20 | # This code is identical to bootasm.S except: 21 | # - it does not need to enable A20 22 | # - it uses the address at start-4, start-8, and start-12 23 | 24 | .code16 25 | .globl start 26 | start: 27 | cli 28 | 29 | xorw %ax,%ax 30 | movw %ax,%ds 31 | movw %ax,%es 32 | movw %ax,%ss 33 | 34 | lgdt gdtdesc 35 | movl %cr0, %eax 36 | orl $CR0_PE, %eax 37 | movl %eax, %cr0 38 | 39 | //PAGEBREAK! 40 | ljmpl $(SEG_KCODE<<3), $(start32) 41 | 42 | .code32 43 | start32: 44 | movw $(SEG_KDATA<<3), %ax 45 | movw %ax, %ds 46 | movw %ax, %es 47 | movw %ax, %ss 48 | movw $0, %ax 49 | movw %ax, %fs 50 | movw %ax, %gs 51 | 52 | # Turn on page size extension for 4Mbyte pages 53 | movl %cr4, %eax 54 | orl $(CR4_PSE), %eax 55 | movl %eax, %cr4 56 | # Use enterpgdir as our initial page table 57 | movl (start-12), %eax 58 | movl %eax, %cr3 59 | # Turn on paging. 60 | movl %cr0, %eax 61 | orl $(CR0_PE|CR0_PG|CR0_WP), %eax 62 | movl %eax, %cr0 63 | 64 | # Switch to the stack allocated by startothers() 65 | movl (start-4), %esp 66 | # Call mpenter() 67 | call *(start-8) 68 | 69 | movw $0x8a00, %ax 70 | movw %ax, %dx 71 | outw %ax, %dx 72 | movw $0x8ae0, %ax 73 | outw %ax, %dx 74 | spin: 75 | jmp spin 76 | 77 | .p2align 2 78 | gdt: 79 | SEG_NULLASM 80 | SEG_ASM(STA_X|STA_R, 0, 0xffffffff) 81 | SEG_ASM(STA_W, 0, 0xffffffff) 82 | 83 | 84 | gdtdesc: 85 | .word (gdtdesc - gdt - 1) 86 | .long gdt 87 | 88 | -------------------------------------------------------------------------------- /xv6/exec.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "param.h" 3 | #include "memlayout.h" 4 | #include "mmu.h" 5 | #include "proc.h" 6 | #include "defs.h" 7 | #include "x86.h" 8 | #include "elf.h" 9 | 10 | int 11 | exec(char *path, char **argv) 12 | { 13 | char *s, *last; 14 | int i, off; 15 | uint argc, sz, sp, ustack[3+MAXARG+1]; 16 | struct elfhdr elf; 17 | struct inode *ip; 18 | struct proghdr ph; 19 | pde_t *pgdir, *oldpgdir; 20 | 21 | begin_op(); 22 | if((ip = namei(path)) == 0){ 23 | end_op(); 24 | return -1; 25 | } 26 | ilock(ip); 27 | pgdir = 0; 28 | 29 | // Check ELF header 30 | if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) 31 | goto bad; 32 | if(elf.magic != ELF_MAGIC) 33 | goto bad; 34 | 35 | if((pgdir = setupkvm()) == 0) 36 | goto bad; 37 | 38 | // Load program into memory. 39 | sz = 0; 40 | for(i=0, off=elf.phoff; i= MAXARG) 67 | goto bad; 68 | sp = (sp - (strlen(argv[argc]) + 1)) & ~3; 69 | if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) 70 | goto bad; 71 | ustack[3+argc] = sp; 72 | } 73 | ustack[3+argc] = 0; 74 | 75 | ustack[0] = 0xffffffff; // fake return PC 76 | ustack[1] = argc; 77 | ustack[2] = sp - (argc+1)*4; // argv pointer 78 | 79 | sp -= (3+argc+1) * 4; 80 | if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) 81 | goto bad; 82 | 83 | // Save program name for debugging. 84 | for(last=s=path; *s; s++) 85 | if(*s == '/') 86 | last = s+1; 87 | safestrcpy(proc->name, last, sizeof(proc->name)); 88 | 89 | // Commit to the user image. 90 | oldpgdir = proc->pgdir; 91 | proc->pgdir = pgdir; 92 | proc->sz = sz; 93 | proc->tf->eip = elf.entry; // main 94 | proc->tf->esp = sp; 95 | switchuvm(proc); 96 | freevm(oldpgdir); 97 | return 0; 98 | 99 | bad: 100 | if(pgdir) 101 | freevm(pgdir); 102 | if(ip){ 103 | iunlockput(ip); 104 | end_op(); 105 | } 106 | return -1; 107 | } 108 | -------------------------------------------------------------------------------- /xv6/fcntl.h: -------------------------------------------------------------------------------- 1 | #define O_RDONLY 0x000 2 | #define O_WRONLY 0x001 3 | #define O_RDWR 0x002 4 | #define O_CREATE 0x200 5 | -------------------------------------------------------------------------------- /xv6/file.c: -------------------------------------------------------------------------------- 1 | // 2 | // File descriptors 3 | // 4 | 5 | #include "types.h" 6 | #include "defs.h" 7 | #include "param.h" 8 | #include "fs.h" 9 | #include "file.h" 10 | #include "spinlock.h" 11 | 12 | struct devsw devsw[NDEV]; 13 | struct { 14 | struct spinlock lock; 15 | struct file file[NFILE]; 16 | } ftable; 17 | 18 | void 19 | fileinit(void) 20 | { 21 | initlock(&ftable.lock, "ftable"); 22 | } 23 | 24 | // Allocate a file structure. 25 | struct file* 26 | filealloc(void) 27 | { 28 | struct file *f; 29 | 30 | acquire(&ftable.lock); 31 | for(f = ftable.file; f < ftable.file + NFILE; f++){ 32 | if(f->ref == 0){ 33 | f->ref = 1; 34 | release(&ftable.lock); 35 | return f; 36 | } 37 | } 38 | release(&ftable.lock); 39 | return 0; 40 | } 41 | 42 | // Increment ref count for file f. 43 | struct file* 44 | filedup(struct file *f) 45 | { 46 | acquire(&ftable.lock); 47 | if(f->ref < 1) 48 | panic("filedup"); 49 | f->ref++; 50 | release(&ftable.lock); 51 | return f; 52 | } 53 | 54 | // Close file f. (Decrement ref count, close when reaches 0.) 55 | void 56 | fileclose(struct file *f) 57 | { 58 | struct file ff; 59 | 60 | acquire(&ftable.lock); 61 | if(f->ref < 1) 62 | panic("fileclose"); 63 | if(--f->ref > 0){ 64 | release(&ftable.lock); 65 | return; 66 | } 67 | ff = *f; 68 | f->ref = 0; 69 | f->type = FD_NONE; 70 | release(&ftable.lock); 71 | 72 | if(ff.type == FD_PIPE) 73 | pipeclose(ff.pipe, ff.writable); 74 | else if(ff.type == FD_INODE){ 75 | begin_op(); 76 | iput(ff.ip); 77 | end_op(); 78 | } 79 | } 80 | 81 | // Get metadata about file f. 82 | int 83 | filestat(struct file *f, struct stat *st) 84 | { 85 | if(f->type == FD_INODE){ 86 | ilock(f->ip); 87 | stati(f->ip, st); 88 | iunlock(f->ip); 89 | return 0; 90 | } 91 | return -1; 92 | } 93 | 94 | // Read from file f. 95 | int 96 | fileread(struct file *f, char *addr, int n) 97 | { 98 | int r; 99 | 100 | if(f->readable == 0) 101 | return -1; 102 | if(f->type == FD_PIPE) 103 | return piperead(f->pipe, addr, n); 104 | if(f->type == FD_INODE){ 105 | ilock(f->ip); 106 | if((r = readi(f->ip, addr, f->off, n)) > 0) 107 | f->off += r; 108 | iunlock(f->ip); 109 | return r; 110 | } 111 | panic("fileread"); 112 | } 113 | 114 | //PAGEBREAK! 115 | // Write to file f. 116 | int 117 | filewrite(struct file *f, char *addr, int n) 118 | { 119 | int r; 120 | 121 | if(f->writable == 0) 122 | return -1; 123 | if(f->type == FD_PIPE) 124 | return pipewrite(f->pipe, addr, n); 125 | if(f->type == FD_INODE){ 126 | // write a few blocks at a time to avoid exceeding 127 | // the maximum log transaction size, including 128 | // i-node, indirect block, allocation blocks, 129 | // and 2 blocks of slop for non-aligned writes. 130 | // this really belongs lower down, since writei() 131 | // might be writing a device like the console. 132 | int max = ((LOGSIZE-1-1-2) / 2) * 512; 133 | int i = 0; 134 | while(i < n){ 135 | int n1 = n - i; 136 | if(n1 > max) 137 | n1 = max; 138 | 139 | begin_op(); 140 | ilock(f->ip); 141 | if ((r = writei(f->ip, addr + i, f->off, n1)) > 0) 142 | f->off += r; 143 | iunlock(f->ip); 144 | end_op(); 145 | 146 | if(r < 0) 147 | break; 148 | if(r != n1) 149 | panic("short filewrite"); 150 | i += r; 151 | } 152 | return i == n ? n : -1; 153 | } 154 | panic("filewrite"); 155 | } 156 | 157 | -------------------------------------------------------------------------------- /xv6/file.h: -------------------------------------------------------------------------------- 1 | struct file { 2 | enum { FD_NONE, FD_PIPE, FD_INODE } type; 3 | int ref; // reference count 4 | char readable; 5 | char writable; 6 | struct pipe *pipe; 7 | struct inode *ip; 8 | uint off; 9 | }; 10 | 11 | 12 | // in-memory copy of an inode 13 | struct inode { 14 | uint dev; // Device number 15 | uint inum; // Inode number 16 | int ref; // Reference count 17 | int flags; // I_BUSY, I_VALID 18 | 19 | short type; // copy of disk inode 20 | short major; 21 | short minor; 22 | short nlink; 23 | uint size; 24 | uint addrs[NDIRECT+1]; 25 | }; 26 | #define I_BUSY 0x1 27 | #define I_VALID 0x2 28 | 29 | // table mapping major device number to 30 | // device functions 31 | struct devsw { 32 | int (*read)(struct inode*, char*, int); 33 | int (*write)(struct inode*, char*, int); 34 | }; 35 | 36 | extern struct devsw devsw[]; 37 | 38 | #define CONSOLE 1 39 | 40 | //PAGEBREAK! 41 | // Blank page. 42 | -------------------------------------------------------------------------------- /xv6/file_icon_big.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/file_icon_big.bmp -------------------------------------------------------------------------------- /xv6/file_icon_small.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/file_icon_small.bmp -------------------------------------------------------------------------------- /xv6/finder.h: -------------------------------------------------------------------------------- 1 | #define TOOLSBAR_COLOR 0xc618 2 | #define TOOLSBAR_HEIGHT 50 3 | 4 | int isSearching; 5 | int renaming; -------------------------------------------------------------------------------- /xv6/folder_icon_big.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/folder_icon_big.bmp -------------------------------------------------------------------------------- /xv6/folder_icon_small.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/folder_icon_small.bmp -------------------------------------------------------------------------------- /xv6/foldericon.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/foldericon.bmp -------------------------------------------------------------------------------- /xv6/forktest.c: -------------------------------------------------------------------------------- 1 | // Test that fork fails gracefully. 2 | // Tiny executable so that the limit can be filling the proc table. 3 | 4 | #include "types.h" 5 | #include "stat.h" 6 | #include "user.h" 7 | 8 | #define N 1000 9 | 10 | void 11 | printf(int fd, char *s, ...) 12 | { 13 | write(fd, s, strlen(s)); 14 | } 15 | 16 | void 17 | forktest(void) 18 | { 19 | int n, pid; 20 | 21 | printf(1, "fork test\n"); 22 | 23 | for(n=0; n 0; n--){ 37 | if(wait() < 0){ 38 | printf(1, "wait stopped early\n"); 39 | exit(); 40 | } 41 | } 42 | 43 | if(wait() != -1){ 44 | printf(1, "wait got too many\n"); 45 | exit(); 46 | } 47 | 48 | printf(1, "fork test OK\n"); 49 | } 50 | 51 | int 52 | main(void) 53 | { 54 | forktest(); 55 | exit(); 56 | } 57 | -------------------------------------------------------------------------------- /xv6/fs.h: -------------------------------------------------------------------------------- 1 | // On-disk file system format. 2 | // Both the kernel and user programs use this header file. 3 | 4 | // Block 0 is unused. 5 | // Block 1 is super block. 6 | // Blocks 2 through sb.ninodes/IPB hold inodes. 7 | // Then free bitmap blocks holding sb.size bits. 8 | // Then sb.nblocks data blocks. 9 | // Then sb.nlog log blocks. 10 | 11 | #define ROOTINO 1 // root i-number 12 | #define BSIZE 512 // block size 13 | 14 | // File system super block 15 | struct superblock { 16 | uint size; // Size of file system image (blocks) 17 | uint nblocks; // Number of data blocks 18 | uint ninodes; // Number of inodes. 19 | uint nlog; // Number of log blocks 20 | }; 21 | 22 | #define NDIRECT 12 23 | #define NINDIRECT (BSIZE / sizeof(uint)) 24 | #define MAXFILE (NDIRECT + NINDIRECT) 25 | 26 | // On-disk inode structure 27 | struct dinode { 28 | short type; // File type 29 | short major; // Major device number (T_DEV only) 30 | short minor; // Minor device number (T_DEV only) 31 | short nlink; // Number of links to inode in file system 32 | uint size; // Size of file (bytes) 33 | uint addrs[NDIRECT+1]; // Data block addresses 34 | }; 35 | 36 | // Inodes per block. 37 | #define IPB (BSIZE / sizeof(struct dinode)) 38 | 39 | // Block containing inode i 40 | #define IBLOCK(i) ((i) / IPB + 2) 41 | 42 | // Bitmap bits per block 43 | #define BPB (BSIZE*8) 44 | 45 | // Block containing bit for block b 46 | #define BBLOCK(b, ninodes) (b/BPB + (ninodes)/IPB + 3) 47 | 48 | // Directory is a file containing a sequence of dirent structures. 49 | #define DIRSIZ 14 50 | 51 | struct dirent { 52 | ushort inum; 53 | char name[DIRSIZ]; 54 | }; 55 | 56 | -------------------------------------------------------------------------------- /xv6/gamecenter.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/gamecenter.bmp -------------------------------------------------------------------------------- /xv6/grep.c: -------------------------------------------------------------------------------- 1 | // Simple grep. Only supports ^ . * $ operators. 2 | 3 | #include "types.h" 4 | #include "stat.h" 5 | #include "user.h" 6 | 7 | char buf[1024]; 8 | int match(char*, char*); 9 | 10 | void 11 | grep(char *pattern, int fd) 12 | { 13 | int n, m; 14 | char *p, *q; 15 | 16 | m = 0; 17 | while((n = read(fd, buf+m, sizeof(buf)-m)) > 0){ 18 | m += n; 19 | p = buf; 20 | while((q = strchr(p, '\n')) != 0){ 21 | *q = 0; 22 | if(match(pattern, p)){ 23 | *q = '\n'; 24 | write(1, p, q+1 - p); 25 | } 26 | p = q+1; 27 | } 28 | if(p == buf) 29 | m = 0; 30 | if(m > 0){ 31 | m -= p - buf; 32 | memmove(buf, p, m); 33 | } 34 | } 35 | } 36 | 37 | int 38 | main(int argc, char *argv[]) 39 | { 40 | int fd, i; 41 | char *pattern; 42 | 43 | if(argc <= 1){ 44 | printf(2, "usage: grep pattern [file ...]\n"); 45 | exit(); 46 | } 47 | pattern = argv[1]; 48 | 49 | if(argc <= 2){ 50 | grep(pattern, 0); 51 | exit(); 52 | } 53 | 54 | for(i = 2; i < argc; i++){ 55 | if((fd = open(argv[i], 0)) < 0){ 56 | printf(1, "grep: cannot open %s\n", argv[i]); 57 | exit(); 58 | } 59 | grep(pattern, fd); 60 | close(fd); 61 | } 62 | exit(); 63 | } 64 | 65 | // Regexp matcher from Kernighan & Pike, 66 | // The Practice of Programming, Chapter 9. 67 | 68 | int matchhere(char*, char*); 69 | int matchstar(int, char*, char*); 70 | 71 | int 72 | match(char *re, char *text) 73 | { 74 | if(re[0] == '^') 75 | return matchhere(re+1, text); 76 | do{ // must look at empty string 77 | if(matchhere(re, text)) 78 | return 1; 79 | }while(*text++ != '\0'); 80 | return 0; 81 | } 82 | 83 | // matchhere: search for re at beginning of text 84 | int matchhere(char *re, char *text) 85 | { 86 | if(re[0] == '\0') 87 | return 1; 88 | if(re[1] == '*') 89 | return matchstar(re[0], re+2, text); 90 | if(re[0] == '$' && re[1] == '\0') 91 | return *text == '\0'; 92 | if(*text!='\0' && (re[0]=='.' || re[0]==*text)) 93 | return matchhere(re+1, text+1); 94 | return 0; 95 | } 96 | 97 | // matchstar: search for c*re at beginning of text 98 | int matchstar(int c, char *re, char *text) 99 | { 100 | do{ // a * matches zero or more instances 101 | if(matchhere(re, text)) 102 | return 1; 103 | }while(*text!='\0' && (*text++==c || c=='.')); 104 | return 0; 105 | } 106 | 107 | -------------------------------------------------------------------------------- /xv6/huffman.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/huffman.c -------------------------------------------------------------------------------- /xv6/huffman.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/huffman.h -------------------------------------------------------------------------------- /xv6/ide.c: -------------------------------------------------------------------------------- 1 | // Simple PIO-based (non-DMA) IDE driver code. 2 | 3 | #include "types.h" 4 | #include "defs.h" 5 | #include "param.h" 6 | #include "memlayout.h" 7 | #include "mmu.h" 8 | #include "proc.h" 9 | #include "x86.h" 10 | #include "traps.h" 11 | #include "spinlock.h" 12 | #include "buf.h" 13 | 14 | #define IDE_BSY 0x80 15 | #define IDE_DRDY 0x40 16 | #define IDE_DF 0x20 17 | #define IDE_ERR 0x01 18 | 19 | #define IDE_CMD_READ 0x20 20 | #define IDE_CMD_WRITE 0x30 21 | 22 | // idequeue points to the buf now being read/written to the disk. 23 | // idequeue->qnext points to the next buf to be processed. 24 | // You must hold idelock while manipulating queue. 25 | 26 | static struct spinlock idelock; 27 | static struct buf *idequeue; 28 | 29 | static int havedisk1; 30 | static void idestart(struct buf*); 31 | 32 | // Wait for IDE disk to become ready. 33 | static int 34 | idewait(int checkerr) 35 | { 36 | int r; 37 | 38 | while(((r = inb(0x1f7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY) 39 | ; 40 | if(checkerr && (r & (IDE_DF|IDE_ERR)) != 0) 41 | return -1; 42 | return 0; 43 | } 44 | 45 | void 46 | ideinit(void) 47 | { 48 | int i; 49 | 50 | initlock(&idelock, "ide"); 51 | picenable(IRQ_IDE); 52 | ioapicenable(IRQ_IDE, ncpu - 1); 53 | idewait(0); 54 | 55 | // Check if disk 1 is present 56 | outb(0x1f6, 0xe0 | (1<<4)); 57 | for(i=0; i<1000; i++){ 58 | if(inb(0x1f7) != 0){ 59 | havedisk1 = 1; 60 | break; 61 | } 62 | } 63 | 64 | // Switch back to disk 0. 65 | outb(0x1f6, 0xe0 | (0<<4)); 66 | } 67 | 68 | // Start the request for b. Caller must hold idelock. 69 | static void 70 | idestart(struct buf *b) 71 | { 72 | if(b == 0) 73 | panic("idestart"); 74 | 75 | idewait(0); 76 | outb(0x3f6, 0); // generate interrupt 77 | outb(0x1f2, 1); // number of sectors 78 | outb(0x1f3, b->sector & 0xff); 79 | outb(0x1f4, (b->sector >> 8) & 0xff); 80 | outb(0x1f5, (b->sector >> 16) & 0xff); 81 | outb(0x1f6, 0xe0 | ((b->dev&1)<<4) | ((b->sector>>24)&0x0f)); 82 | if(b->flags & B_DIRTY){ 83 | outb(0x1f7, IDE_CMD_WRITE); 84 | outsl(0x1f0, b->data, 512/4); 85 | } else { 86 | outb(0x1f7, IDE_CMD_READ); 87 | } 88 | } 89 | 90 | // Interrupt handler. 91 | void 92 | ideintr(void) 93 | { 94 | struct buf *b; 95 | 96 | // First queued buffer is the active request. 97 | acquire(&idelock); 98 | if((b = idequeue) == 0){ 99 | release(&idelock); 100 | // cprintf("spurious IDE interrupt\n"); 101 | return; 102 | } 103 | idequeue = b->qnext; 104 | 105 | // Read data if needed. 106 | if(!(b->flags & B_DIRTY) && idewait(1) >= 0) 107 | insl(0x1f0, b->data, 512/4); 108 | 109 | // Wake process waiting for this buf. 110 | b->flags |= B_VALID; 111 | b->flags &= ~B_DIRTY; 112 | wakeup(b); 113 | 114 | // Start disk on next buf in queue. 115 | if(idequeue != 0) 116 | idestart(idequeue); 117 | 118 | release(&idelock); 119 | } 120 | 121 | //PAGEBREAK! 122 | // Sync buf with disk. 123 | // If B_DIRTY is set, write buf to disk, clear B_DIRTY, set B_VALID. 124 | // Else if B_VALID is not set, read buf from disk, set B_VALID. 125 | void 126 | iderw(struct buf *b) 127 | { 128 | struct buf **pp; 129 | 130 | if(!(b->flags & B_BUSY)) 131 | panic("iderw: buf not busy"); 132 | if((b->flags & (B_VALID|B_DIRTY)) == B_VALID) 133 | panic("iderw: nothing to do"); 134 | if(b->dev != 0 && !havedisk1) 135 | panic("iderw: ide disk 1 not present"); 136 | 137 | acquire(&idelock); //DOC:acquire-lock 138 | 139 | // Append b to idequeue. 140 | b->qnext = 0; 141 | for(pp=&idequeue; *pp; pp=&(*pp)->qnext) //DOC:insert-queue 142 | ; 143 | *pp = b; 144 | 145 | // Start disk if necessary. 146 | if(idequeue == b) 147 | idestart(b); 148 | 149 | // Wait for request to finish. 150 | while((b->flags & (B_VALID|B_DIRTY)) != B_VALID){ 151 | sleep(b, &idelock); 152 | } 153 | 154 | release(&idelock); 155 | } 156 | -------------------------------------------------------------------------------- /xv6/in.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/in.mp3 -------------------------------------------------------------------------------- /xv6/init.c: -------------------------------------------------------------------------------- 1 | // init: The initial user-level program 2 | 3 | #include "types.h" 4 | #include "stat.h" 5 | #include "user.h" 6 | #include "fcntl.h" 7 | 8 | 9 | //char *argv[] = { "sh", 0 }; 10 | char *desktop_argv[] = { "desktop", 0 }; 11 | 12 | int 13 | main(void) 14 | { 15 | int /*pid, wpid,*/ desktop_pid, desktop_wpid; 16 | 17 | if(open("console", O_RDWR) < 0){ 18 | mknod("console", 1, 1); 19 | open("console", O_RDWR); 20 | } 21 | dup(0); // stdout 22 | dup(0); // stderr 23 | 24 | for(;;){ 25 | // 桌面进程 26 | printf(1, "init desktop: starting desktop\n"); 27 | desktop_pid = fork(); 28 | if (desktop_pid < 0) { 29 | printf(1, "init desktop: init desktop failed\n"); 30 | exit(); 31 | } 32 | if (desktop_pid == 0) { 33 | exec("desktop", desktop_argv); 34 | printf(1, "init desktop: exec desktop failed\n"); 35 | exit(); 36 | } 37 | 38 | /* 39 | printf(1, "init: starting sh\n"); 40 | pid = fork(); 41 | if(pid < 0){ 42 | printf(1, "init: fork failed\n"); 43 | exit(); 44 | } 45 | if(pid == 0){ 46 | exec("sh", argv); 47 | printf(1, "init: exec sh failed\n"); 48 | exit(); 49 | } 50 | */ 51 | 52 | while((desktop_wpid=wait()) >= 0 && desktop_wpid != desktop_pid) 53 | printf(1, "desktop finished!\n"); 54 | 55 | //while((wpid=wait()) >= 0 && wpid != pid) 56 | // printf(1, "zombie!\n"); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /xv6/initcode.S: -------------------------------------------------------------------------------- 1 | # Initial process execs /init. 2 | 3 | #include "syscall.h" 4 | #include "traps.h" 5 | 6 | 7 | # exec(init, argv) 8 | .globl start 9 | start: 10 | pushl $argv 11 | pushl $init 12 | pushl $0 // where caller pc would be 13 | movl $SYS_exec, %eax 14 | int $T_SYSCALL 15 | 16 | # for(;;) exit(); 17 | exit: 18 | movl $SYS_exit, %eax 19 | int $T_SYSCALL 20 | jmp exit 21 | 22 | # char init[] = "/init\0"; 23 | init: 24 | .string "/init\0" 25 | 26 | # char *argv[] = { init, 0 }; 27 | .p2align 2 28 | argv: 29 | .long init 30 | .long 0 31 | 32 | -------------------------------------------------------------------------------- /xv6/ioapic.c: -------------------------------------------------------------------------------- 1 | // The I/O APIC manages hardware interrupts for an SMP system. 2 | // http://www.intel.com/design/chipsets/datashts/29056601.pdf 3 | // See also picirq.c. 4 | 5 | #include "types.h" 6 | #include "defs.h" 7 | #include "traps.h" 8 | 9 | #define IOAPIC 0xFEC00000 // Default physical address of IO APIC 10 | 11 | #define REG_ID 0x00 // Register index: ID 12 | #define REG_VER 0x01 // Register index: version 13 | #define REG_TABLE 0x10 // Redirection table base 14 | 15 | // The redirection table starts at REG_TABLE and uses 16 | // two registers to configure each interrupt. 17 | // The first (low) register in a pair contains configuration bits. 18 | // The second (high) register contains a bitmask telling which 19 | // CPUs can serve that interrupt. 20 | #define INT_DISABLED 0x00010000 // Interrupt disabled 21 | #define INT_LEVEL 0x00008000 // Level-triggered (vs edge-) 22 | #define INT_ACTIVELOW 0x00002000 // Active low (vs high) 23 | #define INT_LOGICAL 0x00000800 // Destination is CPU id (vs APIC ID) 24 | 25 | volatile struct ioapic *ioapic; 26 | 27 | // IO APIC MMIO structure: write reg, then read or write data. 28 | struct ioapic { 29 | uint reg; 30 | uint pad[3]; 31 | uint data; 32 | }; 33 | 34 | static uint 35 | ioapicread(int reg) 36 | { 37 | ioapic->reg = reg; 38 | return ioapic->data; 39 | } 40 | 41 | static void 42 | ioapicwrite(int reg, uint data) 43 | { 44 | ioapic->reg = reg; 45 | ioapic->data = data; 46 | } 47 | 48 | void 49 | ioapicinit(void) 50 | { 51 | int i, id, maxintr; 52 | 53 | if(!ismp) 54 | return; 55 | 56 | ioapic = (volatile struct ioapic*)IOAPIC; 57 | maxintr = (ioapicread(REG_VER) >> 16) & 0xFF; 58 | id = ioapicread(REG_ID) >> 24; 59 | if(id != ioapicid) 60 | cprintf("ioapicinit: id isn't equal to ioapicid; not a MP\n"); 61 | 62 | // Mark all interrupts edge-triggered, active high, disabled, 63 | // and not routed to any CPUs. 64 | for(i = 0; i <= maxintr; i++){ 65 | ioapicwrite(REG_TABLE+2*i, INT_DISABLED | (T_IRQ0 + i)); 66 | ioapicwrite(REG_TABLE+2*i+1, 0); 67 | } 68 | } 69 | 70 | void 71 | ioapicenable(int irq, int cpunum) 72 | { 73 | if(!ismp) 74 | return; 75 | 76 | // Mark interrupt edge-triggered, active high, 77 | // enabled, and routed to the given cpunum, 78 | // which happens to be that cpu's APIC ID. 79 | ioapicwrite(REG_TABLE+2*irq, T_IRQ0 + irq); 80 | ioapicwrite(REG_TABLE+2*irq+1, cpunum << 24); 81 | } 82 | -------------------------------------------------------------------------------- /xv6/kalloc.c: -------------------------------------------------------------------------------- 1 | // Physical memory allocator, intended to allocate 2 | // memory for user processes, kernel stacks, page table pages, 3 | // and pipe buffers. Allocates 4096-byte pages. 4 | 5 | #include "types.h" 6 | #include "defs.h" 7 | #include "param.h" 8 | #include "memlayout.h" 9 | #include "mmu.h" 10 | #include "spinlock.h" 11 | 12 | void freerange(void *vstart, void *vend); 13 | extern char end[]; // first address after kernel loaded from ELF file 14 | 15 | struct run { 16 | struct run *next; 17 | }; 18 | 19 | struct { 20 | struct spinlock lock; 21 | int use_lock; 22 | struct run *freelist; 23 | } kmem; 24 | 25 | // Initialization happens in two phases. 26 | // 1. main() calls kinit1() while still using entrypgdir to place just 27 | // the pages mapped by entrypgdir on free list. 28 | // 2. main() calls kinit2() with the rest of the physical pages 29 | // after installing a full page table that maps them on all cores. 30 | void 31 | kinit1(void *vstart, void *vend) 32 | { 33 | initlock(&kmem.lock, "kmem"); 34 | kmem.use_lock = 0; 35 | freerange(vstart, vend); 36 | } 37 | 38 | void 39 | kinit2(void *vstart, void *vend) 40 | { 41 | freerange(vstart, vend); 42 | kmem.use_lock = 1; 43 | } 44 | 45 | void 46 | freerange(void *vstart, void *vend) 47 | { 48 | char *p; 49 | p = (char*)PGROUNDUP((uint)vstart); 50 | for(; p + PGSIZE <= (char*)vend; p += PGSIZE) 51 | kfree(p); 52 | } 53 | 54 | //PAGEBREAK: 21 55 | // Free the page of physical memory pointed at by v, 56 | // which normally should have been returned by a 57 | // call to kalloc(). (The exception is when 58 | // initializing the allocator; see kinit above.) 59 | void 60 | kfree(char *v) 61 | { 62 | struct run *r; 63 | 64 | if((uint)v % PGSIZE || v < end || v2p(v) >= PHYSTOP) 65 | panic("kfree"); 66 | 67 | // Fill with junk to catch dangling refs. 68 | memset(v, 1, PGSIZE); 69 | 70 | if(kmem.use_lock) 71 | acquire(&kmem.lock); 72 | r = (struct run*)v; 73 | r->next = kmem.freelist; 74 | kmem.freelist = r; 75 | if(kmem.use_lock) 76 | release(&kmem.lock); 77 | } 78 | 79 | // Allocate one 4096-byte page of physical memory. 80 | // Returns a pointer that the kernel can use. 81 | // Returns 0 if the memory cannot be allocated. 82 | char* 83 | kalloc(void) 84 | { 85 | struct run *r; 86 | 87 | if(kmem.use_lock) 88 | acquire(&kmem.lock); 89 | r = kmem.freelist; 90 | if(r) 91 | kmem.freelist = r->next; 92 | if(kmem.use_lock) 93 | release(&kmem.lock); 94 | return (char*)r; 95 | } 96 | 97 | -------------------------------------------------------------------------------- /xv6/kbd.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "x86.h" 3 | #include "defs.h" 4 | #include "kbd.h" 5 | #include "window.h" 6 | //#include "gui.h" 7 | #include "message.h" 8 | 9 | static int flag_caps = 0; 10 | static int flag_shift = 0; 11 | //static int flag = 0; 12 | 13 | void 14 | kbdintr(void) 15 | { 16 | uint ch; 17 | ch = inb(0x64); 18 | if((ch & 0x01) == 0) 19 | { 20 | //cprintf("no data\n"); 21 | return; 22 | } 23 | 24 | ch = inb(0x60); 25 | 26 | //press down 27 | if((ch & 0x80) == 0) 28 | { 29 | //flag 30 | int flag_temp; 31 | flag_temp = shiftcode[ch]; 32 | if(flag_temp != NO) 33 | { 34 | flag_shift = flag_temp; 35 | return; 36 | } 37 | 38 | //caps lock 39 | if(togglecode[ch] == CAPSLOCK) 40 | { 41 | //cprintf("caps\n"); 42 | flag_caps = 1; 43 | return; 44 | } 45 | 46 | //get result 47 | char result; 48 | if(flag_caps == 0) 49 | { 50 | switch(flag_shift) 51 | { 52 | case SHIFT: 53 | result = shiftmap[ch]; 54 | break; 55 | case CTL: 56 | result = ctlmap[ch]; 57 | break; 58 | default: 59 | result = normalmap[ch]; 60 | break; 61 | } 62 | } 63 | else 64 | { 65 | switch(flag_shift) 66 | { 67 | case SHIFT: 68 | result = normalmap[ch]; 69 | break; 70 | case CTL: 71 | result = ctlmap[ch]; 72 | break; 73 | default: 74 | result = shiftmap[ch]; 75 | break; 76 | } 77 | } 78 | 79 | createMsg(MSG_KEYDOWN, 0, 0, result); 80 | 81 | 82 | //cprintf("ch: %d\n", ch); 83 | 84 | // if(ch == 1) 85 | // flag = KBD_ESC; 86 | // else if(ch == 75) 87 | // flag = KBD_LEFT; 88 | // else if(ch == 77) 89 | // flag = KBD_RIGHT; 90 | // else if(ch == 72) 91 | // flag = KBD_UP; 92 | // else if(ch == 80) 93 | // flag = KBD_DOWN; 94 | // else 95 | // flag = 0; 96 | 97 | // int cur_icon = WindowLine->next->Cur_icon; 98 | // if(cur_icon == ICON_TEXT) 99 | // { 100 | // kbd_text(result, flag); 101 | // } 102 | // else if(cur_icon == ICON_PHOTO) 103 | // photo(result, flag); 104 | } 105 | //release 106 | else 107 | { 108 | ch = ch & 0x7F; 109 | 110 | //caps lock 111 | if(togglecode[ch] == CAPSLOCK) 112 | { 113 | //cprintf("caps\n"); 114 | flag_caps = 0; 115 | } 116 | 117 | //shift 118 | if(shiftcode[ch] == flag_shift) 119 | { 120 | //cprintf("shift\n"); 121 | flag_shift = NO; 122 | } 123 | 124 | return; 125 | } 126 | } 127 | 128 | /* 129 | int 130 | kbdgetc(void) 131 | { 132 | static uint shift; 133 | static uchar *charcode[4] = { 134 | normalmap, shiftmap, ctlmap, ctlmap 135 | }; 136 | uint st, data, c; 137 | 138 | st = inb(KBSTATP); 139 | if((st & KBS_DIB) == 0) 140 | return -1; 141 | data = inb(KBDATAP); 142 | 143 | if(data == 0xE0){ 144 | shift |= E0ESC; 145 | return 0; 146 | } else if(data & 0x80){ 147 | // Key released 148 | data = (shift & E0ESC ? data : data & 0x7F); 149 | shift &= ~(shiftcode[data] | E0ESC); 150 | return 0; 151 | } else if(shift & E0ESC){ 152 | // Last character was an E0 escape; or with 0x80 153 | data |= 0x80; 154 | shift &= ~E0ESC; 155 | } 156 | 157 | shift |= shiftcode[data]; 158 | shift ^= togglecode[data]; 159 | c = charcode[shift & (CTL | SHIFT)][data]; 160 | if(shift & CAPSLOCK){ 161 | if('a' <= c && c <= 'z') 162 | c += 'A' - 'a'; 163 | else if('A' <= c && c <= 'Z') 164 | c += 'a' - 'A'; 165 | } 166 | return c; 167 | } 168 | */ -------------------------------------------------------------------------------- /xv6/kbd.h: -------------------------------------------------------------------------------- 1 | // PC keyboard interface constants 2 | 3 | #define KBSTATP 0x64 // kbd controller status port(I) 4 | #define KBS_DIB 0x01 // kbd data in buffer 5 | #define KBDATAP 0x60 // kbd data port(I) 6 | 7 | #define NO 0 8 | 9 | #define SHIFT (1<<0) 10 | #define CTL (1<<1) 11 | #define ALT (1<<2) 12 | 13 | #define CAPSLOCK (1<<3) 14 | #define NUMLOCK (1<<4) 15 | #define SCROLLLOCK (1<<5) 16 | 17 | #define E0ESC (1<<6) 18 | 19 | // Special keycodes 20 | #define KEY_HOME 0xE0 21 | #define KEY_END 0xE1 22 | #define KEY_UP 0xE2 23 | #define KEY_DN 0xE3 24 | #define KEY_LF 0xE4 25 | #define KEY_RT 0xE5 26 | #define KEY_PGUP 0xE6 27 | #define KEY_PGDN 0xE7 28 | #define KEY_INS 0xE8 29 | #define KEY_DEL 0xE9 30 | 31 | // C('A') == Control-A 32 | #define C(x) (x - '@') 33 | 34 | static uchar shiftcode[256] = 35 | { 36 | [0x1D] CTL, 37 | [0x2A] SHIFT, 38 | [0x36] SHIFT, 39 | [0x38] ALT, 40 | [0x9D] CTL, 41 | [0xB8] ALT 42 | }; 43 | 44 | static uchar togglecode[256] = 45 | { 46 | [0x3A] CAPSLOCK, 47 | [0x45] NUMLOCK, 48 | [0x46] SCROLLLOCK 49 | }; 50 | 51 | static uchar normalmap[256] = 52 | { 53 | NO, 0x1B, '1', '2', '3', '4', '5', '6', // 0x00 54 | '7', '8', '9', '0', '-', '=', '\b', '\t', 55 | 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', // 0x10 56 | 'o', 'p', '[', ']', '\n', NO, 'a', 's', 57 | 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', // 0x20 58 | '\'', '`', NO, '\\', 'z', 'x', 'c', 'v', 59 | 'b', 'n', 'm', ',', '.', '/', NO, '*', // 0x30 60 | NO, ' ', NO, NO, NO, NO, NO, NO, 61 | NO, NO, NO, NO, NO, NO, NO, '7', // 0x40 62 | '8', '9', '-', '4', '5', '6', '+', '1', 63 | '2', '3', '0', '.', NO, NO, NO, NO, // 0x50 64 | [0x9C] '\n', // KP_Enter 65 | [0xB5] '/', // KP_Div 66 | [0xC8] KEY_UP, [0xD0] KEY_DN, 67 | [0xC9] KEY_PGUP, [0xD1] KEY_PGDN, 68 | [0xCB] KEY_LF, [0xCD] KEY_RT, 69 | [0x97] KEY_HOME, [0xCF] KEY_END, 70 | [0xD2] KEY_INS, [0xD3] KEY_DEL 71 | }; 72 | 73 | static uchar shiftmap[256] = 74 | { 75 | NO, 033, '!', '@', '#', '$', '%', '^', // 0x00 76 | '&', '*', '(', ')', '_', '+', '\b', '\t', 77 | 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', // 0x10 78 | 'O', 'P', '{', '}', '\n', NO, 'A', 'S', 79 | 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', // 0x20 80 | '"', '~', NO, '|', 'Z', 'X', 'C', 'V', 81 | 'B', 'N', 'M', '<', '>', '?', NO, '*', // 0x30 82 | NO, ' ', NO, NO, NO, NO, NO, NO, 83 | NO, NO, NO, NO, NO, NO, NO, '7', // 0x40 84 | '8', '9', '-', '4', '5', '6', '+', '1', 85 | '2', '3', '0', '.', NO, NO, NO, NO, // 0x50 86 | [0x9C] '\n', // KP_Enter 87 | [0xB5] '/', // KP_Div 88 | [0xC8] KEY_UP, [0xD0] KEY_DN, 89 | [0xC9] KEY_PGUP, [0xD1] KEY_PGDN, 90 | [0xCB] KEY_LF, [0xCD] KEY_RT, 91 | [0x97] KEY_HOME, [0xCF] KEY_END, 92 | [0xD2] KEY_INS, [0xD3] KEY_DEL 93 | }; 94 | 95 | static uchar ctlmap[256] = 96 | { 97 | NO, NO, NO, NO, NO, NO, NO, NO, 98 | NO, NO, NO, NO, NO, NO, NO, NO, 99 | C('Q'), C('W'), C('E'), C('R'), C('T'), C('Y'), C('U'), C('I'), 100 | C('O'), C('P'), NO, NO, '\r', NO, C('A'), C('S'), 101 | C('D'), C('F'), C('G'), C('H'), C('J'), C('K'), C('L'), NO, 102 | NO, NO, NO, C('\\'), C('Z'), C('X'), C('C'), C('V'), 103 | C('B'), C('N'), C('M'), NO, NO, C('/'), NO, NO, 104 | [0x9C] '\r', // KP_Enter 105 | [0xB5] C('/'), // KP_Div 106 | [0xC8] KEY_UP, [0xD0] KEY_DN, 107 | [0xC9] KEY_PGUP, [0xD1] KEY_PGDN, 108 | [0xCB] KEY_LF, [0xCD] KEY_RT, 109 | [0x97] KEY_HOME, [0xCF] KEY_END, 110 | [0xD2] KEY_INS, [0xD3] KEY_DEL 111 | }; 112 | 113 | -------------------------------------------------------------------------------- /xv6/kernel.ld: -------------------------------------------------------------------------------- 1 | /* Simple linker script for the JOS kernel. 2 | See the GNU ld 'info' manual ("info ld") to learn the syntax. */ 3 | 4 | OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") 5 | OUTPUT_ARCH(i386) 6 | ENTRY(_start) 7 | 8 | SECTIONS 9 | { 10 | /* Link the kernel at this address: "." means the current address */ 11 | /* Must be equal to KERNLINK */ 12 | . = 0x80100000; 13 | 14 | .text : AT(0x100000) { 15 | *(.text .stub .text.* .gnu.linkonce.t.*) 16 | } 17 | 18 | PROVIDE(etext = .); /* Define the 'etext' symbol to this value */ 19 | 20 | .rodata : { 21 | *(.rodata .rodata.* .gnu.linkonce.r.*) 22 | } 23 | 24 | /* Include debugging information in kernel memory */ 25 | .stab : { 26 | PROVIDE(__STAB_BEGIN__ = .); 27 | *(.stab); 28 | PROVIDE(__STAB_END__ = .); 29 | BYTE(0) /* Force the linker to allocate space 30 | for this section */ 31 | } 32 | 33 | .stabstr : { 34 | PROVIDE(__STABSTR_BEGIN__ = .); 35 | *(.stabstr); 36 | PROVIDE(__STABSTR_END__ = .); 37 | BYTE(0) /* Force the linker to allocate space 38 | for this section */ 39 | } 40 | 41 | /* Adjust the address for the data segment to the next page */ 42 | . = ALIGN(0x1000); 43 | 44 | /* Conventionally, Unix linkers provide pseudo-symbols 45 | * etext, edata, and end, at the end of the text, data, and bss. 46 | * For the kernel mapping, we need the address at the beginning 47 | * of the data section, but that's not one of the conventional 48 | * symbols, because the convention started before there was a 49 | * read-only rodata section between text and data. */ 50 | PROVIDE(data = .); 51 | 52 | /* The data segment */ 53 | .data : { 54 | *(.data) 55 | } 56 | 57 | PROVIDE(edata = .); 58 | 59 | .bss : { 60 | *(.bss) 61 | } 62 | 63 | PROVIDE(end = .); 64 | 65 | /DISCARD/ : { 66 | *(.eh_frame .note.GNU-stack) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /xv6/kill.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char **argv) 7 | { 8 | int i; 9 | 10 | if(argc < 1){ 11 | printf(2, "usage: kill pid...\n"); 12 | exit(); 13 | } 14 | for(i=1; i= path && *p != '/'; p--) 14 | ; 15 | p++; 16 | 17 | // Return blank-padded name. 18 | if(strlen(p) >= DIRSIZ) 19 | return p; 20 | memmove(buf, p, strlen(p)); 21 | memset(buf+strlen(p), ' ', DIRSIZ-strlen(p)); 22 | return buf; 23 | } 24 | 25 | void 26 | ls(char *path) 27 | { 28 | char buf[512], *p; 29 | int fd; 30 | struct dirent de; 31 | struct stat st; 32 | 33 | if((fd = open(path, 0)) < 0){ 34 | printf(2, "ls: cannot open %s\n", path); 35 | return; 36 | } 37 | 38 | if(fstat(fd, &st) < 0){ 39 | printf(2, "ls: cannot stat %s\n", path); 40 | close(fd); 41 | return; 42 | } 43 | 44 | switch(st.type){ 45 | case T_FILE: 46 | printf(1, "%s %d %d %d\n", fmtname(path), st.type, st.ino, st.size); 47 | break; 48 | 49 | case T_DIR: 50 | if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){ 51 | printf(1, "ls: path too long\n"); 52 | break; 53 | } 54 | strcpy(buf, path); 55 | p = buf+strlen(buf); 56 | *p++ = '/'; 57 | while(read(fd, &de, sizeof(de)) == sizeof(de)){ 58 | if(de.inum == 0) 59 | continue; 60 | memmove(p, de.name, DIRSIZ); 61 | p[DIRSIZ] = 0; 62 | if(stat(buf, &st) < 0){ 63 | printf(1, "ls: cannot stat %s\n", buf); 64 | continue; 65 | } 66 | printf(1, "%s %d %d %d\n", fmtname(buf), st.type, st.ino, st.size); 67 | } 68 | break; 69 | } 70 | close(fd); 71 | } 72 | 73 | int 74 | main(int argc, char *argv[]) 75 | { 76 | int i; 77 | 78 | if(argc < 2){ 79 | ls("."); 80 | exit(); 81 | } 82 | for(i=1; iid); 28 | picinit(); // interrupt controller 29 | ioapicinit(); // another interrupt controller 30 | consoleinit(); // I/O devices & their interrupts 31 | uartinit(); // serial port 32 | pinit(); // process table 33 | tvinit(); // trap vectors 34 | binit(); // buffer cache 35 | fileinit(); // file table 36 | iinit(); // inode cache 37 | ideinit(); // disk 38 | soundinit(); // audio 39 | vesamodeinit(); // init VESA mode information 40 | msgqueueinit(); 41 | msgtableinit(); 42 | windowlistinit(); 43 | mouseinit(); 44 | if(!ismp) 45 | timerinit(); // uniprocessor timer 46 | startothers(); // start other processors 47 | kinit2(P2V(4*1024*1024), P2V(PHYSTOP)); // must come after startothers() 48 | userinit(); // first user process 49 | // Finish setting up this processor in mpmain. 50 | mpmain(); 51 | } 52 | 53 | // Other CPUs jump here from entryother.S. 54 | static void 55 | mpenter(void) 56 | { 57 | switchkvm(); 58 | seginit(); 59 | lapicinit(); 60 | mpmain(); 61 | } 62 | 63 | // Common CPU setup code. 64 | static void 65 | mpmain(void) 66 | { 67 | cprintf("cpu%d: starting\n", cpu->id); 68 | idtinit(); // load idt register 69 | xchg(&cpu->started, 1); // tell startothers() we're up 70 | scheduler(); // start running processes 71 | } 72 | 73 | pde_t entrypgdir[]; // For entry.S 74 | 75 | // Start the non-boot (AP) processors. 76 | static void 77 | startothers(void) 78 | { 79 | extern uchar _binary_entryother_start[], _binary_entryother_size[]; 80 | uchar *code; 81 | struct cpu *c; 82 | char *stack; 83 | 84 | // Write entry code to unused memory at 0x7000. 85 | // The linker has placed the image of entryother.S in 86 | // _binary_entryother_start. 87 | code = p2v(0x7000); 88 | memmove(code, _binary_entryother_start, (uint)_binary_entryother_size); 89 | 90 | for(c = cpus; c < cpus+ncpu; c++){ 91 | if(c == cpus+cpunum()) // We've started already. 92 | continue; 93 | 94 | // Tell entryother.S what stack to use, where to enter, and what 95 | // pgdir to use. We cannot use kpgdir yet, because the AP processor 96 | // is running in low memory, so we use entrypgdir for the APs too. 97 | stack = kalloc(); 98 | *(void**)(code-4) = stack + KSTACKSIZE; 99 | *(void**)(code-8) = mpenter; 100 | *(int**)(code-12) = (void *) v2p(entrypgdir); 101 | 102 | lapicstartap(c->id, v2p(code)); 103 | 104 | // wait for cpu to finish mpmain() 105 | while(c->started == 0) 106 | ; 107 | } 108 | } 109 | 110 | // Boot page table used in entry.S and entryother.S. 111 | // Page directories (and page tables), must start on a page boundary, 112 | // hence the "__aligned__" attribute. 113 | // Use PTE_PS in page directory entry to enable 4Mbyte pages. 114 | __attribute__((__aligned__(PGSIZE))) 115 | pde_t entrypgdir[NPDENTRIES] = { 116 | // Map VA's [0, 4MB) to PA's [0, 4MB) 117 | [0] = (0) | PTE_P | PTE_W | PTE_PS, 118 | // Map VA's [KERNBASE, KERNBASE+4MB) to PA's [0, 4MB) 119 | [KERNBASE>>PDXSHIFT] = (0) | PTE_P | PTE_W | PTE_PS, 120 | }; 121 | 122 | //PAGEBREAK! 123 | // Blank page. 124 | //PAGEBREAK! 125 | // Blank page. 126 | //PAGEBREAK! 127 | // Blank page. 128 | -------------------------------------------------------------------------------- /xv6/math.c: -------------------------------------------------------------------------------- 1 | #include "math.h" 2 | #define pi 3.1415926535898 3 | int abs(int x) 4 | { 5 | if (x < 0) 6 | return x * -1; 7 | else 8 | return x; 9 | } 10 | double sin(double x) 11 | { 12 | double Result=x,Fac=1.0,Xn=x,Precious=x; 13 | int n=1,sign=1; 14 | while(Precious>1e-6) 15 | { 16 | n = n+1; 17 | Fac=Fac*n*(n + 1); 18 | n = n + 1; 19 | Xn*=x*x; 20 | sign=-sign; 21 | Precious=Xn/Fac; 22 | Result=sign>0?Result+Precious:Result-Precious; 23 | } 24 | return Result; 25 | } 26 | double cos(double x) 27 | { 28 | return sin(pi/2-x); 29 | } 30 | double tan(double x) 31 | { 32 | return sin(x)/cos(x); 33 | } 34 | 35 | double pow(double x, double y) 36 | { 37 | if(x==0 && y!=0) return 0; 38 | else if(x==0 && y==0) return 1; 39 | else if(y<0) return 1/pow(x,-y);//把指数小于0的情况转为1/x^-y计算 40 | else if(x<0 && y-(int)y!=0) return 0;//若x为负,且y不为整数数,则出错,返回0 41 | else if(x<0 && y-(int)y==0)//若x为负,且y为整数数,则用循环计算 42 | { 43 | double powint=1; 44 | int i; 45 | for(i=1;i<=y;i++) powint*=x; 46 | return powint; 47 | } 48 | return exp(y*ln(x)); 49 | } 50 | // 求根 51 | double sqrt(double x) 52 | { 53 | return pow(x,0.5); 54 | } 55 | 56 | // ln(x) = 2 arctanh((x-1)/(x+1)) 57 | // 调用了Arctanh(double) 方法 58 | double ln(double x) 59 | { 60 | double y=x-1,ln_p1=0,ln_p2=0,ln_p3=0,ln_px=0,ln_tmp=1,dln_px=1,tmp; 61 | int l; 62 | if(x==1) return 0; 63 | else if(x>2) return -ln(1/x); 64 | else if(x<.1) 65 | { 66 | double n=-1; 67 | double a; 68 | do 69 | { 70 | n=n-.6; 71 | a=x/exp(n); 72 | } 73 | while(a>2 || a<1); 74 | return ln(a)+n; 75 | } 76 | for(l=1,tmp=1;(ln_px-ln_tmp)>1e-9 || (ln_px-ln_tmp)<-1e-9;l++) 77 | { 78 | ln_tmp=ln_px; 79 | tmp*=y; 80 | if(l==1) tmp=tmp/l; 81 | else tmp=tmp/-l; 82 | ln_p1+=tmp; 83 | ln_p2=ln_p1+-1*tmp*y*l/(l+1); 84 | ln_p3=ln_p2+tmp*y*y*l/(l+2); 85 | dln_px=ln_p3-ln_p2; 86 | ln_px=ln_p3-dln_px*dln_px/(ln_p3-2*ln_p2+ln_p1); 87 | tmp*=l; 88 | } 89 | return ln_px; 90 | } 91 | 92 | // 求e^x 用于Pow( double, double )调用 93 | // e^x = 1+x+(x^2)/2!+(x^3)/3!+... 94 | // 精度为7位 95 | double exp( double x ) 96 | { 97 | double y=x,ex_p1=0,ex_p2=0,ex_p3=0,ex_px=0,ex_tmp=1,dex_px=1,tmp; 98 | int l; 99 | if(x==0) return 1; 100 | if(x<0) return 1/exp(-x); 101 | for(l=1,tmp=1;((ex_px-ex_tmp)>1e-10 || (ex_px-ex_tmp)<-1e-10) && dex_px>1e-10;l++) 102 | { 103 | ex_tmp=ex_px; 104 | tmp*=y; 105 | tmp=tmp/l; 106 | ex_p1+=tmp; 107 | ex_p2=ex_p1+tmp*y/(l+1); 108 | ex_p3=ex_p2+tmp*y*y/(l+1)/(l+2); 109 | dex_px=ex_p3-ex_p2; 110 | ex_px=ex_p3-dex_px*dex_px/(ex_p3-2*ex_p2+ex_p1); 111 | } 112 | return ex_px+1; 113 | } -------------------------------------------------------------------------------- /xv6/math.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/math.h -------------------------------------------------------------------------------- /xv6/memide.c: -------------------------------------------------------------------------------- 1 | // Fake IDE disk; stores blocks in memory. 2 | // Useful for running kernel without scratch disk. 3 | 4 | #include "types.h" 5 | #include "defs.h" 6 | #include "param.h" 7 | #include "mmu.h" 8 | #include "proc.h" 9 | #include "x86.h" 10 | #include "traps.h" 11 | #include "spinlock.h" 12 | #include "buf.h" 13 | 14 | extern uchar _binary_fs_img_start[], _binary_fs_img_size[]; 15 | 16 | static int disksize; 17 | static uchar *memdisk; 18 | 19 | void 20 | ideinit(void) 21 | { 22 | memdisk = _binary_fs_img_start; 23 | disksize = (uint)_binary_fs_img_size/512; 24 | } 25 | 26 | // Interrupt handler. 27 | void 28 | ideintr(void) 29 | { 30 | // no-op 31 | } 32 | 33 | // Sync buf with disk. 34 | // If B_DIRTY is set, write buf to disk, clear B_DIRTY, set B_VALID. 35 | // Else if B_VALID is not set, read buf from disk, set B_VALID. 36 | void 37 | iderw(struct buf *b) 38 | { 39 | uchar *p; 40 | 41 | if(!(b->flags & B_BUSY)) 42 | panic("iderw: buf not busy"); 43 | if((b->flags & (B_VALID|B_DIRTY)) == B_VALID) 44 | panic("iderw: nothing to do"); 45 | if(b->dev != 1) 46 | panic("iderw: request not for disk 1"); 47 | if(b->sector >= disksize) 48 | panic("iderw: sector out of range"); 49 | 50 | p = memdisk + b->sector*512; 51 | 52 | if(b->flags & B_DIRTY){ 53 | b->flags &= ~B_DIRTY; 54 | memmove(p, b->data, 512); 55 | } else 56 | memmove(b->data, p, 512); 57 | b->flags |= B_VALID; 58 | } 59 | -------------------------------------------------------------------------------- /xv6/memlayout.h: -------------------------------------------------------------------------------- 1 | // Memory layout 2 | 3 | #define EXTMEM 0x100000 // Start of extended memory 4 | #define PHYSTOP 0xE000000 // Top physical memory 5 | #define DEVSPACE 0xFC000000 // Other devices are at high addresses 6 | 7 | // Key addresses for address space layout (see kmap in vm.c for layout) 8 | #define KERNBASE 0x80000000 // First kernel virtual address 9 | #define KERNLINK (KERNBASE+EXTMEM) // Address where kernel is linked 10 | 11 | #ifndef __ASSEMBLER__ 12 | 13 | static inline uint v2p(void *a) { return ((uint) (a)) - KERNBASE; } 14 | static inline void *p2v(uint a) { return (void *) ((a) + KERNBASE); } 15 | 16 | #endif 17 | 18 | #define V2P(a) (((uint) (a)) - KERNBASE) 19 | #define P2V(a) (((void *) (a)) + KERNBASE) 20 | 21 | #define V2P_WO(x) ((x) - KERNBASE) // same as V2P, but without casts 22 | #define P2V_WO(x) ((x) + KERNBASE) // same as V2P, but without casts 23 | -------------------------------------------------------------------------------- /xv6/message.h: -------------------------------------------------------------------------------- 1 | #define MSG_NONE 0 2 | #define MSG_UNUSED 0 3 | #define MSG_MOVE 1 4 | #define MSG_LPRESS 2 5 | #define MSG_RPRESS 3 6 | #define MSG_DOUBLECLICK 4 7 | #define MSG_DRAG 5 8 | #define MSG_KEYDOWN 6 9 | #define MSG_UPDATE 7 10 | #define MSG_PARTIAL_UPDATE 8 11 | #define MAX_PROCESS_NUMBER 20 12 | #define MAX_QUEUE_LENGTH 100 13 | 14 | //鼠标消息 15 | typedef struct MsgMouse 16 | { 17 | int x; 18 | int y; 19 | } MsgMouse; 20 | 21 | //键盘消息 22 | typedef struct MsgKey 23 | { 24 | char key; 25 | } MsgKey; 26 | 27 | typedef struct MsgPartialUpdate 28 | { 29 | int x1; 30 | int y1; 31 | int x2; 32 | int y2; 33 | } MsgPartialUpdate; 34 | 35 | typedef struct Msg 36 | { 37 | int msg_type; 38 | int msg_detail; 39 | union 40 | { 41 | struct MsgMouse msg_mouse; 42 | struct MsgKey msg_key; 43 | struct MsgPartialUpdate msg_partial_update; 44 | } concrete_msg; 45 | int next_msg;//下一个消息在全局消息队列中的索引 46 | } Msg; 47 | 48 | //进程消息队列表项 49 | typedef struct MsgTableEntry 50 | { 51 | int pid; 52 | int first_msg;//待处理的第一个消息在全局消息队列中的索引 53 | } MsgTableEntry; 54 | 55 | extern void createMsg(int msg_type, int pos_x, int pos_y, char key); 56 | extern void msgqueueinit(); 57 | extern void msgtableinit(); 58 | extern void createUpdateMsg(int pid, int detail); 59 | extern void createPartialUpdateMsg(int pid, int x1, int y1, int x2, int y2); 60 | -------------------------------------------------------------------------------- /xv6/mkdir.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char *argv[]) 7 | { 8 | int i; 9 | 10 | if(argc < 2){ 11 | printf(2, "Usage: mkdir files...\n"); 12 | exit(); 13 | } 14 | 15 | for(i = 1; i < argc; i++){ 16 | if(mkdir(argv[i]) < 0){ 17 | printf(2, "mkdir: %s failed to create\n", argv[i]); 18 | break; 19 | } 20 | } 21 | 22 | exit(); 23 | } 24 | -------------------------------------------------------------------------------- /xv6/mouse.h: -------------------------------------------------------------------------------- 1 | //mouse event 2 | #define LEFT_CLICK 1 3 | #define RIGHT_CLICK 2 4 | #define DOUBLE_CLICK 3 5 | #define DRAGGING 4 6 | #define DRAG_RELEASE 5 7 | 8 | #define DOUBLE_CLICK_DELAY 30 9 | -------------------------------------------------------------------------------- /xv6/mp.c: -------------------------------------------------------------------------------- 1 | // Multiprocessor support 2 | // Search memory for MP description structures. 3 | // http://developer.intel.com/design/pentium/datashts/24201606.pdf 4 | 5 | #include "types.h" 6 | #include "defs.h" 7 | #include "param.h" 8 | #include "memlayout.h" 9 | #include "mp.h" 10 | #include "x86.h" 11 | #include "mmu.h" 12 | #include "proc.h" 13 | 14 | struct cpu cpus[NCPU]; 15 | static struct cpu *bcpu; 16 | int ismp; 17 | int ncpu; 18 | uchar ioapicid; 19 | 20 | int 21 | mpbcpu(void) 22 | { 23 | return bcpu-cpus; 24 | } 25 | 26 | static uchar 27 | sum(uchar *addr, int len) 28 | { 29 | int i, sum; 30 | 31 | sum = 0; 32 | for(i=0; iphysaddr == 0) 87 | return 0; 88 | conf = (struct mpconf*) p2v((uint) mp->physaddr); 89 | if(memcmp(conf, "PCMP", 4) != 0) 90 | return 0; 91 | if(conf->version != 1 && conf->version != 4) 92 | return 0; 93 | if(sum((uchar*)conf, conf->length) != 0) 94 | return 0; 95 | *pmp = mp; 96 | return conf; 97 | } 98 | 99 | void 100 | mpinit(void) 101 | { 102 | uchar *p, *e; 103 | struct mp *mp; 104 | struct mpconf *conf; 105 | struct mpproc *proc; 106 | struct mpioapic *ioapic; 107 | 108 | bcpu = &cpus[0]; 109 | if((conf = mpconfig(&mp)) == 0) 110 | return; 111 | ismp = 1; 112 | lapic = (uint*)conf->lapicaddr; 113 | for(p=(uchar*)(conf+1), e=(uchar*)conf+conf->length; papicid){ 118 | cprintf("mpinit: ncpu=%d apicid=%d\n", ncpu, proc->apicid); 119 | ismp = 0; 120 | } 121 | if(proc->flags & MPBOOT) 122 | bcpu = &cpus[ncpu]; 123 | cpus[ncpu].id = ncpu; 124 | ncpu++; 125 | p += sizeof(struct mpproc); 126 | continue; 127 | case MPIOAPIC: 128 | ioapic = (struct mpioapic*)p; 129 | ioapicid = ioapic->apicno; 130 | p += sizeof(struct mpioapic); 131 | continue; 132 | case MPBUS: 133 | case MPIOINTR: 134 | case MPLINTR: 135 | p += 8; 136 | continue; 137 | default: 138 | cprintf("mpinit: unknown config type %x\n", *p); 139 | ismp = 0; 140 | } 141 | } 142 | if(!ismp){ 143 | // Didn't like what we found; fall back to no MP. 144 | ncpu = 1; 145 | lapic = 0; 146 | ioapicid = 0; 147 | return; 148 | } 149 | 150 | if(mp->imcrp){ 151 | // Bochs doesn't support IMCR, so this doesn't run on Bochs. 152 | // But it would on real hardware. 153 | outb(0x22, 0x70); // Select IMCR 154 | outb(0x23, inb(0x23) | 1); // Mask external interrupts. 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /xv6/mp.h: -------------------------------------------------------------------------------- 1 | // See MultiProcessor Specification Version 1.[14] 2 | 3 | struct mp { // floating pointer 4 | uchar signature[4]; // "_MP_" 5 | void *physaddr; // phys addr of MP config table 6 | uchar length; // 1 7 | uchar specrev; // [14] 8 | uchar checksum; // all bytes must add up to 0 9 | uchar type; // MP system config type 10 | uchar imcrp; 11 | uchar reserved[3]; 12 | }; 13 | 14 | struct mpconf { // configuration table header 15 | uchar signature[4]; // "PCMP" 16 | ushort length; // total table length 17 | uchar version; // [14] 18 | uchar checksum; // all bytes must add up to 0 19 | uchar product[20]; // product id 20 | uint *oemtable; // OEM table pointer 21 | ushort oemlength; // OEM table length 22 | ushort entry; // entry count 23 | uint *lapicaddr; // address of local APIC 24 | ushort xlength; // extended table length 25 | uchar xchecksum; // extended table checksum 26 | uchar reserved; 27 | }; 28 | 29 | struct mpproc { // processor table entry 30 | uchar type; // entry type (0) 31 | uchar apicid; // local APIC id 32 | uchar version; // local APIC verison 33 | uchar flags; // CPU flags 34 | #define MPBOOT 0x02 // This proc is the bootstrap processor. 35 | uchar signature[4]; // CPU signature 36 | uint feature; // feature flags from CPUID instruction 37 | uchar reserved[8]; 38 | }; 39 | 40 | struct mpioapic { // I/O APIC table entry 41 | uchar type; // entry type (2) 42 | uchar apicno; // I/O APIC id 43 | uchar version; // I/O APIC version 44 | uchar flags; // I/O APIC flags 45 | uint *addr; // I/O APIC address 46 | }; 47 | 48 | // Table entry types 49 | #define MPPROC 0x00 // One per processor 50 | #define MPBUS 0x01 // One per bus 51 | #define MPIOAPIC 0x02 // One per I/O APIC 52 | #define MPIOINTR 0x03 // One per bus interrupt source 53 | #define MPLINTR 0x04 // One per system interrupt source 54 | 55 | //PAGEBREAK! 56 | // Blank page. 57 | -------------------------------------------------------------------------------- /xv6/mp3dec.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "user.h" 3 | #include "sound.h" 4 | #include "common.h" 5 | #include "decode.h" 6 | int main() 7 | { 8 | //struct coreBuf* corebuf; 9 | III_scalefac_t III_scalefac; 10 | typedef short PCM[2][SSLIMIT][SBLIMIT]; 11 | PCM *pcm_sample; 12 | pcm_sample = (PCM *) mem_alloc((long) sizeof(PCM), "PCM Samp"); 13 | unsigned long sample_frames = 0; 14 | //corebuf = (struct coreBuf*)getCoreBuf(); 15 | struct frame_params fr_ps; 16 | struct III_side_info_t III_side_info; 17 | while (1) { 18 | printf(0, "decode\n"); 19 | waitForDecode(&fr_ps, &III_side_info); 20 | int clip = 0, gr, ch, ss, sb; 21 | for (gr=0;gr<2;gr++) { 22 | double lr[2][SBLIMIT][SSLIMIT],ro[2][SBLIMIT][SSLIMIT]; 23 | //Ö÷œâÂë 24 | for (ch=0; ch= 0; i--) 51 | if (argv[1][i] == '/') 52 | break; 53 | i++; 54 | strcpy(&com[len2], &argv[1][i]); 55 | } 56 | 57 | //打开目标文件 58 | int fd_dest = open(com, O_WRONLY|O_CREATE); 59 | if (fd_dest == -1) 60 | { 61 | printf(1, "create dest file failed\n"); 62 | exit(); 63 | } 64 | 65 | //复制文件 66 | char buf[BUF_SIZE] = {}; 67 | int len = 0; 68 | while((len = read(fd_src, buf, BUF_SIZE)) > 0) 69 | write(fd_dest, buf, len); 70 | 71 | //关闭文件 72 | close(fd_src); 73 | close(fd_dest); 74 | 75 | //删除源文件 76 | if(unlink(argv[1]) < 0) 77 | printf(1, "delete source file failed\n"); 78 | 79 | //关闭程序 80 | exit(); 81 | } 82 | 83 | char* fmtname(char *path) 84 | { 85 | static char buf[DIRSIZ+1]; 86 | char *p; 87 | 88 | // Find first character after last slash. 89 | for(p=path+strlen(path); p >= path && *p != '/'; p--) 90 | ; 91 | p++; 92 | 93 | // Return blank-padded name. 94 | if(strlen(p) >= DIRSIZ) 95 | return p; 96 | memmove(buf, p, strlen(p)); 97 | memset(buf+strlen(p), ' ', DIRSIZ-strlen(p)); 98 | return buf; 99 | } 100 | 101 | void ls(char *path) 102 | { 103 | char buf[512], *p; 104 | int fd; 105 | struct dirent de; 106 | struct stat st; 107 | 108 | if((fd = open(path, 0)) < 0) 109 | { 110 | printf(2, "cannot open %s\n", path); 111 | return; 112 | } 113 | 114 | if(fstat(fd, &st) < 0) 115 | { 116 | printf(2, "cannot stat %s\n", path); 117 | close(fd); 118 | return; 119 | } 120 | 121 | switch(st.type) 122 | { 123 | case T_FILE: 124 | printf(1, "name = %s, type = file, size = %d\n", fmtname(path), st.size); 125 | break; 126 | 127 | case T_DIR: 128 | if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf) 129 | { 130 | printf(1, "path too long\n"); 131 | break; 132 | } 133 | strcpy(buf, path); 134 | p = buf+strlen(buf); 135 | *p++ = '/'; 136 | 137 | while(read(fd, &de, sizeof(de)) == sizeof(de)) 138 | { 139 | if(de.inum == 0) 140 | continue; 141 | memmove(p, de.name, DIRSIZ); 142 | p[DIRSIZ] = 0; 143 | if(stat(buf, &st) < 0) 144 | { 145 | printf(1, "cannot stat %s\n", buf); 146 | continue; 147 | } 148 | printf(1, "name = %s, type = directory, size = %d\n", fmtname(buf), st.size); 149 | } 150 | break; 151 | } 152 | close(fd); 153 | } 154 | 155 | -------------------------------------------------------------------------------- /xv6/notes.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/notes.bmp -------------------------------------------------------------------------------- /xv6/param.h: -------------------------------------------------------------------------------- 1 | #define NPROC 64 // maximum number of processes 2 | #define KSTACKSIZE 4096 // size of per-process kernel stack 3 | #define NCPU 8 // maximum number of CPUs 4 | #define NOFILE 16 // open files per process 5 | #define NFILE 100 // open files per system 6 | #define NINODE 50 // maximum number of active i-nodes 7 | #define NDEV 10 // maximum major device number 8 | #define ROOTDEV 1 // device number of file system root disk 9 | #define MAXARG 32 // max exec arguments 10 | #define MAXOPBLOCKS 10 // max # of blocks any FS op writes 11 | #define LOGSIZE (MAXOPBLOCKS*3) // max data sectors in on-disk log 12 | #define NBUF (MAXOPBLOCKS*3) // size of disk block cache 13 | 14 | -------------------------------------------------------------------------------- /xv6/paste.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/paste.bmp -------------------------------------------------------------------------------- /xv6/pause.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/pause.bmp -------------------------------------------------------------------------------- /xv6/pause.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "user.h" 3 | int main() 4 | { 5 | pause(); 6 | exit(); 7 | } 8 | -------------------------------------------------------------------------------- /xv6/picirq.c: -------------------------------------------------------------------------------- 1 | // Intel 8259A programmable interrupt controllers. 2 | 3 | #include "types.h" 4 | #include "x86.h" 5 | #include "traps.h" 6 | 7 | // I/O Addresses of the two programmable interrupt controllers 8 | #define IO_PIC1 0x20 // Master (IRQs 0-7) 9 | #define IO_PIC2 0xA0 // Slave (IRQs 8-15) 10 | 11 | #define IRQ_SLAVE 2 // IRQ at which slave connects to master 12 | 13 | // Current IRQ mask. 14 | // Initial IRQ mask has interrupt 2 enabled (for slave 8259A). 15 | static ushort irqmask = 0xFFFF & ~(1<> 8); 23 | } 24 | 25 | void 26 | picenable(int irq) 27 | { 28 | picsetmask(irqmask & ~(1<readopen = 1; 33 | p->writeopen = 1; 34 | p->nwrite = 0; 35 | p->nread = 0; 36 | initlock(&p->lock, "pipe"); 37 | (*f0)->type = FD_PIPE; 38 | (*f0)->readable = 1; 39 | (*f0)->writable = 0; 40 | (*f0)->pipe = p; 41 | (*f1)->type = FD_PIPE; 42 | (*f1)->readable = 0; 43 | (*f1)->writable = 1; 44 | (*f1)->pipe = p; 45 | return 0; 46 | 47 | //PAGEBREAK: 20 48 | bad: 49 | if(p) 50 | kfree((char*)p); 51 | if(*f0) 52 | fileclose(*f0); 53 | if(*f1) 54 | fileclose(*f1); 55 | return -1; 56 | } 57 | 58 | void 59 | pipeclose(struct pipe *p, int writable) 60 | { 61 | acquire(&p->lock); 62 | if(writable){ 63 | p->writeopen = 0; 64 | wakeup(&p->nread); 65 | } else { 66 | p->readopen = 0; 67 | wakeup(&p->nwrite); 68 | } 69 | if(p->readopen == 0 && p->writeopen == 0){ 70 | release(&p->lock); 71 | kfree((char*)p); 72 | } else 73 | release(&p->lock); 74 | } 75 | 76 | //PAGEBREAK: 40 77 | int 78 | pipewrite(struct pipe *p, char *addr, int n) 79 | { 80 | int i; 81 | 82 | acquire(&p->lock); 83 | for(i = 0; i < n; i++){ 84 | while(p->nwrite == p->nread + PIPESIZE){ //DOC: pipewrite-full 85 | if(p->readopen == 0 || proc->killed){ 86 | release(&p->lock); 87 | return -1; 88 | } 89 | wakeup(&p->nread); 90 | sleep(&p->nwrite, &p->lock); //DOC: pipewrite-sleep 91 | } 92 | p->data[p->nwrite++ % PIPESIZE] = addr[i]; 93 | } 94 | wakeup(&p->nread); //DOC: pipewrite-wakeup1 95 | release(&p->lock); 96 | return n; 97 | } 98 | 99 | int 100 | piperead(struct pipe *p, char *addr, int n) 101 | { 102 | int i; 103 | 104 | acquire(&p->lock); 105 | while(p->nread == p->nwrite && p->writeopen){ //DOC: pipe-empty 106 | if(proc->killed){ 107 | release(&p->lock); 108 | return -1; 109 | } 110 | sleep(&p->nread, &p->lock); //DOC: piperead-sleep 111 | } 112 | for(i = 0; i < n; i++){ //DOC: piperead-copy 113 | if(p->nread == p->nwrite) 114 | break; 115 | addr[i] = p->data[p->nread++ % PIPESIZE]; 116 | } 117 | wakeup(&p->nwrite); //DOC: piperead-wakeup 118 | release(&p->lock); 119 | return i; 120 | } 121 | -------------------------------------------------------------------------------- /xv6/play.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/play.bmp -------------------------------------------------------------------------------- /xv6/play.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | #include "sound.h" 5 | #include "fcntl.h" 6 | 7 | #define SINGLE_BUF_SIZE 4096 8 | #define BUF_SIZE (SINGLE_BUF_SIZE * 8) 9 | 10 | int 11 | main(int argc, char *argv[]) 12 | { 13 | int i; 14 | int fd; 15 | struct wav info; 16 | 17 | fd = open(argv[1], O_RDWR); 18 | if (fd < 0) 19 | { 20 | printf(0, "open wav file fail\n"); 21 | exit(); 22 | } 23 | 24 | read(fd, &info, sizeof(struct wav)); 25 | if ((info.riff_id != 0x46464952)||(info.wave_id != 0x45564157)) { 26 | printf(0, "invalid file format\n"); 27 | close(fd); 28 | exit(); 29 | } 30 | 31 | if ((info.info.id != 0x20746d66)|| 32 | (info.info.channel != 0x0002)|| 33 | (info.info.bytes_per_sample != 0x0004)|| 34 | (info.info.bits_per_sample != 0x0010)) { 35 | printf(0, "data encoded in an unaccepted way\n"); 36 | close(fd); 37 | exit(); 38 | } 39 | 40 | int pid = fork(); 41 | if (pid == 0) { 42 | exec("sh",argv); 43 | } 44 | printf(0, "%d", info.info.sample_rate); 45 | setSampleRate(info.info.sample_rate); 46 | uint rd = 0; 47 | char buf[BUF_SIZE]; 48 | 49 | int mp3pid = fork(); 50 | if (mp3pid == 0) { 51 | exec("decode", argv); 52 | } 53 | while (rd < info.dlen) 54 | { 55 | int len = (info.dlen - rd < BUF_SIZE ? info.dlen - rd : BUF_SIZE); 56 | i = 0; 57 | read(fd, buf, len); 58 | rd += len; 59 | while(len > SINGLE_BUF_SIZE) 60 | { 61 | kwrite(buf+(i++)*SINGLE_BUF_SIZE, SINGLE_BUF_SIZE); 62 | len -= SINGLE_BUF_SIZE; 63 | } 64 | if(len > 0) 65 | kwrite(buf+i*SINGLE_BUF_SIZE, len); 66 | } 67 | 68 | memset(buf, 0, BUF_SIZE); 69 | for (i = 0; i < DMA_BUF_NUM*DMA_BUF_SIZE/BUF_SIZE+1; i++) 70 | { 71 | kwrite(buf, BUF_SIZE); 72 | } 73 | 74 | close(fd); 75 | //kill(pid); 76 | kill(mp3pid); 77 | wait(); 78 | wait(); 79 | exit(); 80 | } 81 | 82 | -------------------------------------------------------------------------------- /xv6/playmp3.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "user.h" 3 | #include "sound.h" 4 | #include "common.h" 5 | #include "decode.h" 6 | 7 | int main(int argc, char**argv) 8 | { 9 | int pid = 0;//fork(); 10 | if (pid == 0) { 11 | // exec("sh",argv); 12 | } 13 | int decodepid = fork(); 14 | if (decodepid == 0) { 15 | exec("mp3dec", argv); 16 | } 17 | int mp3pid = 0;//fork(); 18 | if (mp3pid == 0) { 19 | // exec("decode", argv); 20 | } 21 | printf(0, "start playing mp3\n"); 22 | setSampleRate(44100); 23 | Bit_stream_struc bs; 24 | struct frame_params fr_ps; 25 | struct III_side_info_t III_side_info; 26 | unsigned int old_crc; 27 | layer info; 28 | unsigned long bitsPerSlot; 29 | 30 | /*if (argc==1) { 31 | printf("Useage:decode file.mp3 output.pcm\n"); 32 | return; 33 | }*/ 34 | 35 | fr_ps.header = &info; 36 | 37 | open_bit_stream_r(&bs, argv[1], BUFFER_SIZE); 38 | int frame_Num = 0; 39 | while(!end_bs(&bs)) { 40 | //³¢ÊÔ֡ͬ²œ 41 | seek_sync(&bs, SYNC_WORD, SYNC_WORD_LENGTH); 42 | decode_info(&bs, &(fr_ps)); 43 | //œ«fr_ps.headerÖеÄÐÅÏ¢œâ¶Áµœfr_psµÄÏà¹ØÓòÖÐ 44 | hdr_to_frps(&(fr_ps)); 45 | //Êä³öÏà¹ØÐÅÏ¢ 46 | frame_Num = frame_Num + 1; 47 | printf(0, "read frame: %d\n", frame_Num); 48 | if (info.error_protection) 49 | buffer_CRC(&bs, &old_crc); 50 | switch (info.lay) { 51 | case 3: 52 | { 53 | int nSlots, main_data_end, flush_main; 54 | int bytes_to_discard; 55 | static int frame_start = 0; 56 | 57 | bitsPerSlot = 8; 58 | 59 | //È¡SideÐÅÏ¢ 60 | III_get_side_info(&bs, &(III_side_info), &(fr_ps)); 61 | nSlots = main_data_slots(fr_ps); 62 | //¶ÁÖ÷ÊýŸÝ(Audio Data) 63 | for (; nSlots > 0; nSlots--) /* read main data. */ 64 | hputbuf((unsigned int) getbits(&bs,8), 8); 65 | main_data_end = hsstell() / 8; /*of privious frame*/ 66 | if ( (flush_main=(hsstell() % bitsPerSlot))==TRUE ) { 67 | hgetbits((int)(bitsPerSlot - flush_main)); 68 | main_data_end ++; 69 | } 70 | bytes_to_discard = frame_start - main_data_end - III_side_info.main_data_begin ; 71 | if( main_data_end > 4096 ) { frame_start -= 4096; 72 | rewindNbytes( 4096 ); 73 | } 74 | 75 | frame_start += main_data_slots(fr_ps); 76 | // printf(0, "discard : %d\n", bytes_to_discard); 77 | if (bytes_to_discard < 0) { 78 | printf(0, "discard: %d %d %d\n", frame_start, main_data_end, III_side_info.main_data_begin); 79 | //printf(0, "Not enough main data to decode frame %d. Frame discarded.\n",frame_Num - 1); 80 | break; 81 | } 82 | for (; bytes_to_discard > 0; bytes_to_discard--) hgetbits(8); 83 | beginDecode(&fr_ps, &III_side_info); 84 | } 85 | break; 86 | default: 87 | // printf("\nOnly layer III supported!\n"); 88 | exit(); 89 | break; 90 | } 91 | } 92 | close_bit_stream_r(&bs); 93 | printf(0, "\nPlaying done.\n"); 94 | kill(pid); 95 | kill(decodepid); 96 | kill(mp3pid); 97 | wait(); 98 | wait(); 99 | wait(); 100 | exit(); 101 | } 102 | -------------------------------------------------------------------------------- /xv6/pr.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use POSIX qw(strftime); 4 | 5 | if($ARGV[0] eq "-h"){ 6 | shift @ARGV; 7 | $h = $ARGV[0]; 8 | shift @ARGV; 9 | }else{ 10 | $h = $ARGV[0]; 11 | } 12 | 13 | $page = 0; 14 | $now = strftime "%b %e %H:%M %Y", localtime; 15 | 16 | @lines = <>; 17 | for($i=0; $i<@lines; $i+=50){ 18 | print "\n\n"; 19 | ++$page; 20 | print "$now $h Page $page\n"; 21 | print "\n\n"; 22 | for($j=$i; $j<@lines && $j<$i +50; $j++){ 23 | $lines[$j] =~ s!//DOC.*!!; 24 | print $lines[$j]; 25 | } 26 | for(; $j<$i+50; $j++){ 27 | print "\n"; 28 | } 29 | $sheet = ""; 30 | if($lines[$i] =~ /^([0-9][0-9])[0-9][0-9] /){ 31 | $sheet = "Sheet $1"; 32 | } 33 | print "\n\n"; 34 | print "$sheet\n"; 35 | print "\n\n"; 36 | } 37 | -------------------------------------------------------------------------------- /xv6/printf.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | static void 6 | putc(int fd, char c) 7 | { 8 | write(fd, &c, 1); 9 | } 10 | 11 | static void 12 | printint(int fd, int xx, int base, int sgn) 13 | { 14 | static char digits[] = "0123456789ABCDEF"; 15 | char buf[16]; 16 | int i, neg; 17 | uint x; 18 | 19 | neg = 0; 20 | if(sgn && xx < 0){ 21 | neg = 1; 22 | x = -xx; 23 | } else { 24 | x = xx; 25 | } 26 | 27 | i = 0; 28 | do{ 29 | buf[i++] = digits[x % base]; 30 | }while((x /= base) != 0); 31 | if(neg) 32 | buf[i++] = '-'; 33 | 34 | while(--i >= 0) 35 | putc(fd, buf[i]); 36 | } 37 | 38 | // Print to the given fd. Only understands %d, %x, %p, %s. 39 | void 40 | printf(int fd, char *fmt, ...) 41 | { 42 | char *s; 43 | int c, i, state; 44 | uint *ap; 45 | 46 | state = 0; 47 | ap = (uint*)(void*)&fmt + 1; 48 | for(i = 0; fmt[i]; i++){ 49 | c = fmt[i] & 0xff; 50 | if(state == 0){ 51 | if(c == '%'){ 52 | state = '%'; 53 | } else { 54 | putc(fd, c); 55 | } 56 | } else if(state == '%'){ 57 | if(c == 'd'){ 58 | printint(fd, *ap, 10, 1); 59 | ap++; 60 | } else if(c == 'x' || c == 'p'){ 61 | printint(fd, *ap, 16, 0); 62 | ap++; 63 | } else if(c == 's'){ 64 | s = (char*)*ap; 65 | ap++; 66 | if(s == 0) 67 | s = "(null)"; 68 | while(*s != 0){ 69 | putc(fd, *s); 70 | s++; 71 | } 72 | } else if(c == 'c'){ 73 | putc(fd, *ap); 74 | ap++; 75 | } else if(c == '%'){ 76 | putc(fd, c); 77 | } else { 78 | // Unknown % sequence. Print it to draw attention. 79 | putc(fd, '%'); 80 | putc(fd, c); 81 | } 82 | state = 0; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /xv6/printpcs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Decode the symbols from a panic EIP list 4 | 5 | # Find a working addr2line 6 | for p in i386-jos-elf-addr2line addr2line; do 7 | if which $p 2>&1 >/dev/null && \ 8 | $p -h 2>&1 | grep -q '\belf32-i386\b'; then 9 | break 10 | fi 11 | done 12 | 13 | # Enable as much pretty-printing as this addr2line can do 14 | $p $($p -h | grep ' -[aipsf] ' | awk '{print $1}') -e kernel "$@" 15 | -------------------------------------------------------------------------------- /xv6/proc.h: -------------------------------------------------------------------------------- 1 | // Segments in proc->gdt. 2 | #define NSEGS 7 3 | 4 | // Per-CPU state 5 | struct cpu { 6 | uchar id; // Local APIC ID; index into cpus[] below 7 | struct context *scheduler; // swtch() here to enter scheduler 8 | struct taskstate ts; // Used by x86 to find stack for interrupt 9 | struct segdesc gdt[NSEGS]; // x86 global descriptor table 10 | volatile uint started; // Has the CPU started? 11 | int ncli; // Depth of pushcli nesting. 12 | int intena; // Were interrupts enabled before pushcli? 13 | 14 | // Cpu-local storage variables; see below 15 | struct cpu *cpu; 16 | struct proc *proc; // The currently-running process. 17 | }; 18 | 19 | extern struct cpu cpus[NCPU]; 20 | extern int ncpu; 21 | 22 | // Per-CPU variables, holding pointers to the 23 | // current cpu and to the current process. 24 | // The asm suffix tells gcc to use "%gs:0" to refer to cpu 25 | // and "%gs:4" to refer to proc. seginit sets up the 26 | // %gs segment register so that %gs refers to the memory 27 | // holding those two variables in the local cpu's struct cpu. 28 | // This is similar to how thread-local variables are implemented 29 | // in thread libraries such as Linux pthreads. 30 | extern struct cpu *cpu asm("%gs:0"); // &cpus[cpunum()] 31 | extern struct proc *proc asm("%gs:4"); // cpus[cpunum()].proc 32 | 33 | //PAGEBREAK: 17 34 | // Saved registers for kernel context switches. 35 | // Don't need to save all the segment registers (%cs, etc), 36 | // because they are constant across kernel contexts. 37 | // Don't need to save %eax, %ecx, %edx, because the 38 | // x86 convention is that the caller has saved them. 39 | // Contexts are stored at the bottom of the stack they 40 | // describe; the stack pointer is the address of the context. 41 | // The layout of the context matches the layout of the stack in swtch.S 42 | // at the "Switch stacks" comment. Switch doesn't save eip explicitly, 43 | // but it is on the stack and allocproc() manipulates it. 44 | struct context { 45 | uint edi; 46 | uint esi; 47 | uint ebx; 48 | uint ebp; 49 | uint eip; 50 | }; 51 | 52 | enum procstate { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE }; 53 | 54 | // Per-process state 55 | struct proc { 56 | uint sz; // Size of process memory (bytes) 57 | pde_t* pgdir; // Page table 58 | char *kstack; // Bottom of kernel stack for this process 59 | enum procstate state; // Process state 60 | int pid; // Process ID 61 | struct proc *parent; // Parent process 62 | struct trapframe *tf; // Trap frame for current syscall 63 | struct context *context; // swtch() here to run process 64 | void *chan; // If non-zero, sleeping on chan 65 | int killed; // If non-zero, have been killed 66 | struct file *ofile[NOFILE]; // Open files 67 | struct inode *cwd; // Current directory 68 | char name[16]; // Process name (debugging) 69 | }; 70 | 71 | // Process memory is laid out contiguously, low addresses first: 72 | // text 73 | // original data and bss 74 | // fixed-size stack 75 | // expandable heap 76 | -------------------------------------------------------------------------------- /xv6/qemu.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/qemu.wav -------------------------------------------------------------------------------- /xv6/qian.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/qian.wav -------------------------------------------------------------------------------- /xv6/ren.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char *argv[]) 7 | { 8 | 9 | if(argc != 3){ 10 | printf(2, "Usage: rename filename newfilename\n"); 11 | exit(); 12 | } 13 | // char * dir = argv[3]; 14 | // chdir(dir); 15 | if(link(argv[1], argv[2]) < 0){ 16 | printf(2, "ren: %s failed to rename\n", argv[1]); 17 | exit(); 18 | } 19 | if(unlink(argv[1]) < 0){ 20 | printf(2, "ren: %s failed to unlink the old name\n", argv[1]); 21 | exit(); 22 | } 23 | chdir("/"); 24 | exit(); 25 | } 26 | -------------------------------------------------------------------------------- /xv6/rename.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/rename.bmp -------------------------------------------------------------------------------- /xv6/rm.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char *argv[]) 7 | { 8 | int i; 9 | 10 | if(argc < 2){ 11 | printf(2, "Usage: rm files...\n"); 12 | exit(); 13 | } 14 | 15 | for(i = 1; i < argc; i++){ 16 | if(unlink(argv[i]) < 0){ 17 | printf(2, "rm: %s failed to delete\n", argv[i]); 18 | break; 19 | } 20 | } 21 | 22 | exit(); 23 | } 24 | -------------------------------------------------------------------------------- /xv6/rolldown.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/rolldown.bmp -------------------------------------------------------------------------------- /xv6/rollup.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/rollup.bmp -------------------------------------------------------------------------------- /xv6/runoff.list: -------------------------------------------------------------------------------- 1 | # basic headers 2 | types.h 3 | param.h 4 | memlayout.h 5 | defs.h 6 | x86.h 7 | asm.h 8 | mmu.h 9 | elf.h 10 | 11 | # entering xv6 12 | entry.S 13 | entryother.S 14 | main.c 15 | 16 | # locks 17 | spinlock.h 18 | spinlock.c 19 | 20 | # processes 21 | vm.c 22 | proc.h 23 | proc.c 24 | swtch.S 25 | kalloc.c 26 | 27 | # system calls 28 | traps.h 29 | vectors.pl 30 | trapasm.S 31 | trap.c 32 | syscall.h 33 | syscall.c 34 | sysproc.c 35 | 36 | # file system 37 | buf.h 38 | fcntl.h 39 | stat.h 40 | fs.h 41 | file.h 42 | ide.c 43 | bio.c 44 | log.c 45 | fs.c 46 | file.c 47 | sysfile.c 48 | exec.c 49 | 50 | # pipes 51 | pipe.c 52 | 53 | # string operations 54 | string.c 55 | 56 | # low-level hardware 57 | mp.h 58 | mp.c 59 | lapic.c 60 | ioapic.c 61 | picirq.c 62 | kbd.h 63 | kbd.c 64 | console.c 65 | timer.c 66 | uart.c 67 | 68 | # user-level 69 | initcode.S 70 | usys.S 71 | init.c 72 | sh.c 73 | 74 | # bootloader 75 | bootasm.S 76 | bootmain.c 77 | 78 | -------------------------------------------------------------------------------- /xv6/runoff.spec: -------------------------------------------------------------------------------- 1 | # Is sheet 01 (after the TOC) a left sheet or a right sheet? 2 | sheet1: left 3 | 4 | # "left" and "right" specify which page of a two-page spread a file 5 | # must start on. "left" means that a file must start on the first of 6 | # the two pages. "right" means it must start on the second of the two 7 | # pages. The file may start in either column. 8 | # 9 | # "even" and "odd" specify which column a file must start on. "even" 10 | # means it must start in the left of the two columns (00). "odd" means it 11 | # must start in the right of the two columns (50). 12 | # 13 | # You'd think these would be the other way around. 14 | 15 | # types.h either 16 | # param.h either 17 | # defs.h either 18 | # x86.h either 19 | # asm.h either 20 | # mmu.h either 21 | # elf.h either 22 | # mp.h either 23 | 24 | even: entry.S # mild preference 25 | even: entryother.S # mild preference 26 | even: main.c 27 | # mp.c don't care at all 28 | # even: initcode.S 29 | # odd: init.c 30 | 31 | left: spinlock.h 32 | even: spinlock.h 33 | 34 | # This gets struct proc and allocproc on the same spread 35 | left: proc.h 36 | even: proc.h 37 | 38 | # goal is to have two action-packed 2-page spreads, 39 | # one with 40 | # userinit growproc fork exit wait 41 | # and another with 42 | # scheduler sched yield forkret sleep wakeup1 wakeup 43 | right: proc.c # VERY important 44 | even: proc.c # VERY important 45 | 46 | # A few more action packed spreads 47 | # page table creation and process loading 48 | # walkpgdir mappages setupkvm switch[ku]vm inituvm (loaduvm) 49 | # process memory management 50 | # allocuvm deallocuvm freevm 51 | left: vm.c 52 | 53 | even: kalloc.c # mild preference 54 | 55 | # syscall.h either 56 | # trapasm.S either 57 | # traps.h either 58 | # even: trap.c 59 | # vectors.pl either 60 | # syscall.c either 61 | # sysproc.c either 62 | 63 | # buf.h either 64 | # dev.h either 65 | # fcntl.h either 66 | # stat.h either 67 | # file.h either 68 | # fs.h either 69 | # fsvar.h either 70 | # left: ide.c # mild preference 71 | even: ide.c 72 | # odd: bio.c 73 | 74 | # log.c fits nicely in a spread 75 | even: log.c 76 | left: log.c 77 | 78 | # with fs.c starting on 2nd column of a left page, we get these 2-page spreads: 79 | # ialloc iupdate iget idup ilock iunlock iput iunlockput 80 | # bmap itrunc stati readi writei 81 | # namecmp dirlookup dirlink skipelem namex namei 82 | # fileinit filealloc filedup fileclose filestat fileread filewrite 83 | # starting on 2nd column of a right page is not terrible either 84 | odd: fs.c # VERY important 85 | left: fs.c # mild preference 86 | # file.c either 87 | # exec.c either 88 | # sysfile.c either 89 | 90 | # Mild preference, but makes spreads of mp.c, lapic.c, and ioapic.c+picirq.c 91 | even: mp.c 92 | left: mp.c 93 | 94 | # even: pipe.c # mild preference 95 | # string.c either 96 | # left: kbd.h # mild preference 97 | even: kbd.h 98 | even: console.c 99 | odd: sh.c 100 | 101 | even: bootasm.S # mild preference 102 | even: bootmain.c # mild preference 103 | -------------------------------------------------------------------------------- /xv6/runoff1: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | $n = 0; 4 | $v = 0; 5 | if($ARGV[0] eq "-v") { 6 | $v = 1; 7 | shift @ARGV; 8 | } 9 | if($ARGV[0] eq "-n") { 10 | $n = $ARGV[1]; 11 | shift @ARGV; 12 | shift @ARGV; 13 | } 14 | $n = int(($n+49)/50)*50 - 1; 15 | 16 | $file = $ARGV[0]; 17 | @lines = <>; 18 | $linenum = 0; 19 | foreach (@lines) { 20 | $linenum++; 21 | chomp; 22 | s/\s+$//; 23 | if(length() >= 75){ 24 | print STDERR "$file:$linenum: line too long\n"; 25 | } 26 | } 27 | @outlines = (); 28 | $nextout = 0; 29 | 30 | for($i=0; $i<@lines; ){ 31 | # Skip leading blank lines. 32 | $i++ while $i<@lines && $lines[$i] =~ /^$/; 33 | last if $i>=@lines; 34 | 35 | # If the rest of the file fits, use the whole thing. 36 | if(@lines <= $i+50 && !grep { /PAGEBREAK/ } @lines){ 37 | $breakbefore = @lines; 38 | }else{ 39 | # Find a good next page break; 40 | # Hope for end of function. 41 | # but settle for a blank line (but not first blank line 42 | # in function, which comes after variable declarations). 43 | $breakbefore = $i; 44 | $lastblank = $i; 45 | $sawbrace = 0; 46 | $breaksize = 15; # 15 lines to get to function 47 | for($j=$i; $j<$i+50 && $j < @lines; $j++){ 48 | if($lines[$j] =~ /PAGEBREAK!/){ 49 | $lines[$j] = ""; 50 | $breakbefore = $j; 51 | $breaksize = 100; 52 | last; 53 | } 54 | if($lines[$j] =~ /PAGEBREAK:\s*([0-9]+)/){ 55 | $breaksize = $1; 56 | $breakbefore = $j; 57 | $lines[$j] = ""; 58 | } 59 | if($lines[$j] =~ /^};?$/){ 60 | $breakbefore = $j+1; 61 | $breaksize = 15; 62 | } 63 | if($lines[$j] =~ /^{$/){ 64 | $sawbrace = 1; 65 | } 66 | if($lines[$j] =~ /^$/){ 67 | if($sawbrace){ 68 | $sawbrace = 0; 69 | }else{ 70 | $lastblank = $j; 71 | } 72 | } 73 | } 74 | if($j<@lines && $lines[$j] =~ /^$/){ 75 | $lastblank = $j; 76 | } 77 | 78 | # If we are not putting enough on a page, try a blank line. 79 | if($breakbefore - $i < 50 - $breaksize && $lastblank > $breakbefore && $lastblank >= $i+50 - 5){ 80 | if($v){ 81 | print STDERR "breakbefore $breakbefore i $i breaksize $breaksize\n"; 82 | } 83 | $breakbefore = $lastblank; 84 | $breaksize = 5; # only 5 lines to get to blank line 85 | } 86 | 87 | # If we are not putting enough on a page, force a full page. 88 | if($breakbefore - $i < 50 - $breaksize && $breakbefore != @lines){ 89 | $breakbefore = $i + 50; 90 | $breakbefore = @lines if @lines < $breakbefore; 91 | } 92 | 93 | if($breakbefore < $i+2){ 94 | $breakbefore = $i+2; 95 | } 96 | } 97 | 98 | # Emit the page. 99 | $i50 = $i + 50; 100 | for(; $i<$breakbefore; $i++){ 101 | printf "%04d %s\n", ++$n, $lines[$i]; 102 | } 103 | 104 | # Finish page 105 | for($j=$i; $j<$i50; $j++){ 106 | printf "%04d \n", ++$n; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /xv6/save.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/save.bmp -------------------------------------------------------------------------------- /xv6/search.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/search.bmp -------------------------------------------------------------------------------- /xv6/setting.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/setting.bmp -------------------------------------------------------------------------------- /xv6/show1: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | runoff1 "$@" | pr.pl -h "xv6/$@" | mpage -m50t50b -o -bLetter -T -t -2 -FLucidaSans-Typewriter83 -L60 >x.ps; gv --swap x.ps 4 | -------------------------------------------------------------------------------- /xv6/sign.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!"; 4 | 5 | $n = sysread(SIG, $buf, 1000); 6 | 7 | if($n > 510){ 8 | print STDERR "boot block too large: $n bytes (max 510)\n"; 9 | exit 1; 10 | } 11 | 12 | print STDERR "boot block is $n bytes (max 510)\n"; 13 | 14 | $buf .= "\0" x (510-$n); 15 | $buf .= "\x55\xAA"; 16 | 17 | open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!"; 18 | print SIG $buf; 19 | close SIG; 20 | -------------------------------------------------------------------------------- /xv6/sleep1.p: -------------------------------------------------------------------------------- 1 | /* 2 | This file defines a Promela model for xv6's 3 | acquire, release, sleep, and wakeup, along with 4 | a model of a simple producer/consumer queue. 5 | 6 | To run: 7 | spinp sleep1.p 8 | 9 | (You may need to install Spin, available at http://spinroot.com/.) 10 | 11 | After a successful run spin prints something like: 12 | 13 | unreached in proctype consumer 14 | (0 of 37 states) 15 | unreached in proctype producer 16 | (0 of 23 states) 17 | 18 | After an unsuccessful run, the spinp script prints 19 | an execution trace that causes a deadlock. 20 | 21 | The safe body of producer reads: 22 | 23 | acquire(lk); 24 | x = value; value = x + 1; x = 0; 25 | wakeup(0); 26 | release(lk); 27 | i = i + 1; 28 | 29 | If this is changed to: 30 | 31 | x = value; value = x + 1; x = 0; 32 | acquire(lk); 33 | wakeup(0); 34 | release(lk); 35 | i = i + 1; 36 | 37 | then a deadlock can happen, because the non-atomic 38 | increment of value conflicts with the non-atomic 39 | decrement in consumer, causing value to have a bad value. 40 | Try this. 41 | 42 | If it is changed to: 43 | 44 | acquire(lk); 45 | x = value; value = x + 1; x = 0; 46 | release(lk); 47 | wakeup(0); 48 | i = i + 1; 49 | 50 | then nothing bad happens: it is okay to wakeup after release 51 | instead of before, although it seems morally wrong. 52 | */ 53 | 54 | #define ITER 4 55 | #define N 2 56 | 57 | bit lk; 58 | byte value; 59 | bit sleeping[N]; 60 | 61 | inline acquire(x) 62 | { 63 | atomic { x == 0; x = 1 } 64 | } 65 | 66 | inline release(x) 67 | { 68 | assert x==1; 69 | x = 0 70 | } 71 | 72 | inline sleep(cond, lk) 73 | { 74 | assert !sleeping[_pid]; 75 | if 76 | :: cond -> 77 | skip 78 | :: else -> 79 | atomic { release(lk); sleeping[_pid] = 1 }; 80 | sleeping[_pid] == 0; 81 | acquire(lk) 82 | fi 83 | } 84 | 85 | inline wakeup() 86 | { 87 | w = 0; 88 | do 89 | :: w < N -> 90 | sleeping[w] = 0; 91 | w = w + 1 92 | :: else -> 93 | break 94 | od 95 | } 96 | 97 | active[N] proctype consumer() 98 | { 99 | byte i, x; 100 | 101 | i = 0; 102 | do 103 | :: i < ITER -> 104 | acquire(lk); 105 | sleep(value > 0, lk); 106 | x = value; value = x - 1; x = 0; 107 | release(lk); 108 | i = i + 1; 109 | :: else -> 110 | break 111 | od; 112 | i = 0; 113 | skip 114 | } 115 | 116 | active[N] proctype producer() 117 | { 118 | byte i, x, w; 119 | 120 | i = 0; 121 | do 122 | :: i < ITER -> 123 | acquire(lk); 124 | x = value; value = x + 1; x = 0; 125 | release(lk); 126 | wakeup(); 127 | i = i + 1; 128 | :: else -> 129 | break 130 | od; 131 | i = 0; 132 | skip 133 | } 134 | 135 | -------------------------------------------------------------------------------- /xv6/sound.h: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | #define DMA_BUF_NUM 32 4 | #define DMA_SMP_NUM 0x80 5 | #define DMA_BUF_SIZE (DMA_SMP_NUM*2) 6 | 7 | struct fmt { 8 | uint id; 9 | uint len; 10 | ushort pad; 11 | ushort channel; 12 | uint sample_rate; 13 | uint bytes_per_sec; 14 | ushort bytes_per_sample; 15 | ushort bits_per_sample; 16 | }; 17 | 18 | struct wav{ 19 | uint riff_id; 20 | uint rlen; 21 | uint wave_id; 22 | struct fmt info; 23 | uint data_id; 24 | uint dlen; 25 | }; 26 | 27 | #define BUFSIZE 4096 28 | struct coreBuf{ 29 | unsigned int buf[BUFSIZE]; 30 | unsigned int buf_bit_idx; 31 | unsigned long offset, totbit, buf_byte_idx; 32 | struct frame_params fr_ps; 33 | struct III_side_info_t III_side_info; 34 | }; 35 | 36 | 37 | struct soundNode{ 38 | volatile int flag; 39 | struct soundNode *next; 40 | uchar data[DMA_BUF_NUM*DMA_BUF_SIZE]; 41 | }; 42 | 43 | void addSound(struct soundNode *node); 44 | 45 | #define PROCESSED 0x1 46 | #define PCM_OUT 0x2 47 | #define PCM_IN 0x4 48 | -------------------------------------------------------------------------------- /xv6/spinlock.c: -------------------------------------------------------------------------------- 1 | // Mutual exclusion spin locks. 2 | 3 | #include "types.h" 4 | #include "defs.h" 5 | #include "param.h" 6 | #include "x86.h" 7 | #include "memlayout.h" 8 | #include "mmu.h" 9 | #include "proc.h" 10 | #include "spinlock.h" 11 | 12 | void 13 | initlock(struct spinlock *lk, char *name) 14 | { 15 | lk->name = name; 16 | lk->locked = 0; 17 | lk->cpu = 0; 18 | } 19 | 20 | // Acquire the lock. 21 | // Loops (spins) until the lock is acquired. 22 | // Holding a lock for a long time may cause 23 | // other CPUs to waste time spinning to acquire it. 24 | void 25 | acquire(struct spinlock *lk) 26 | { 27 | pushcli(); // disable interrupts to avoid deadlock. 28 | if(holding(lk)) 29 | panic("acquire"); 30 | 31 | // The xchg is atomic. 32 | // It also serializes, so that reads after acquire are not 33 | // reordered before it. 34 | while(xchg(&lk->locked, 1) != 0) 35 | ; 36 | 37 | // Record info about lock acquisition for debugging. 38 | lk->cpu = cpu; 39 | getcallerpcs(&lk, lk->pcs); 40 | } 41 | 42 | // Release the lock. 43 | void 44 | release(struct spinlock *lk) 45 | { 46 | if(!holding(lk)) 47 | panic("release"); 48 | 49 | lk->pcs[0] = 0; 50 | lk->cpu = 0; 51 | 52 | // The xchg serializes, so that reads before release are 53 | // not reordered after it. The 1996 PentiumPro manual (Volume 3, 54 | // 7.2) says reads can be carried out speculatively and in 55 | // any order, which implies we need to serialize here. 56 | // But the 2007 Intel 64 Architecture Memory Ordering White 57 | // Paper says that Intel 64 and IA-32 will not move a load 58 | // after a store. So lock->locked = 0 would work here. 59 | // The xchg being asm volatile ensures gcc emits it after 60 | // the above assignments (and after the critical section). 61 | xchg(&lk->locked, 0); 62 | 63 | popcli(); 64 | } 65 | 66 | // Record the current call stack in pcs[] by following the %ebp chain. 67 | void 68 | getcallerpcs(void *v, uint pcs[]) 69 | { 70 | uint *ebp; 71 | int i; 72 | 73 | ebp = (uint*)v - 2; 74 | for(i = 0; i < 10; i++){ 75 | if(ebp == 0 || ebp < (uint*)KERNBASE || ebp == (uint*)0xffffffff) 76 | break; 77 | pcs[i] = ebp[1]; // saved %eip 78 | ebp = (uint*)ebp[0]; // saved %ebp 79 | } 80 | for(; i < 10; i++) 81 | pcs[i] = 0; 82 | } 83 | 84 | // Check whether this cpu is holding the lock. 85 | int 86 | holding(struct spinlock *lock) 87 | { 88 | return lock->locked && lock->cpu == cpu; 89 | } 90 | 91 | 92 | // Pushcli/popcli are like cli/sti except that they are matched: 93 | // it takes two popcli to undo two pushcli. Also, if interrupts 94 | // are off, then pushcli, popcli leaves them off. 95 | 96 | void 97 | pushcli(void) 98 | { 99 | int eflags; 100 | 101 | eflags = readeflags(); 102 | cli(); 103 | if(cpu->ncli++ == 0) 104 | cpu->intena = eflags & FL_IF; 105 | } 106 | 107 | void 108 | popcli(void) 109 | { 110 | if(readeflags()&FL_IF) 111 | panic("popcli - interruptible"); 112 | if(--cpu->ncli < 0) 113 | panic("popcli"); 114 | if(cpu->ncli == 0 && cpu->intena) 115 | sti(); 116 | } 117 | 118 | -------------------------------------------------------------------------------- /xv6/spinlock.h: -------------------------------------------------------------------------------- 1 | // Mutual exclusion lock. 2 | struct spinlock { 3 | uint locked; // Is the lock held? 4 | 5 | // For debugging: 6 | char *name; // Name of lock. 7 | struct cpu *cpu; // The cpu holding the lock. 8 | uint pcs[10]; // The call stack (an array of program counters) 9 | // that locked the lock. 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /xv6/spinp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $# != 1 ] || [ ! -f "$1" ]; then 4 | echo 'usage: spinp file.p' 1>&2 5 | exit 1 6 | fi 7 | 8 | rm -f $1.trail 9 | spin -a $1 || exit 1 10 | cc -DSAFETY -DREACH -DMEMLIM=500 -o pan pan.c 11 | pan -i 12 | rm pan.* pan 13 | if [ -f $1.trail ]; then 14 | spin -t -p $1 15 | fi 16 | 17 | -------------------------------------------------------------------------------- /xv6/splice.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | #include "fcntl.h" 5 | 6 | 7 | char buf[512]; 8 | void write_bet_fds(int src_fd, int dst_fd); 9 | /* 10 | * This function is made to do files catch 11 | * The result text will be stored in the dst_file 12 | */ 13 | void 14 | splice(int num, char *src_files[], char* dst_file){//源文件数、源文件名[]、目标文件名 15 | int src_fd, dst_fd; 16 | int i; 17 | for (i=0;i 0){ 53 | write(dst_fd, buf, strlen(buf)); 54 | memset(buf, 0, strlen(buf)); // clear the buffer 55 | } 56 | 57 | if (n < 0){ 58 | printf(1, "splice: read error\n"); 59 | chdir("/"); 60 | exit(); 61 | } 62 | } 63 | 64 | int 65 | main(int argc, char *argv[]) 66 | { 67 | //char *dir; 68 | if (argc <= 1){//只输入一个splice而不输入参数时 69 | printf(2, "Usage: splice many files to one file...\n"); 70 | chdir("/");//切换默认目录 71 | exit();//终止进程 72 | } 73 | //dir = argv[argc];//dir变成最后一个传入参数,也就是目标文件名 74 | //chdir(dir); 75 | 76 | // format: cat filename 77 | // read the content of filename 78 | if (argc <= 3){//后面只带一两个参数 79 | printf(2, "Use a format:\'splice src_file1 src_file2 dst_file\'\n"); 80 | chdir("/"); 81 | exit(); 82 | } 83 | else{//cat的参数>=3个 84 | //参数大于两个的时候,拼接文件 85 | splice(argc - 2, argv + 1, argv[argc - 1]); 86 | } 87 | chdir("/"); 88 | exit(); 89 | } 90 | 91 | -------------------------------------------------------------------------------- /xv6/stat.h: -------------------------------------------------------------------------------- 1 | #define T_DIR 1 // Directory 2 | #define T_FILE 2 // File 3 | #define T_DEV 3 // Device 4 | 5 | struct stat { 6 | short type; // Type of file 7 | int dev; // File system's disk device 8 | uint ino; // Inode number 9 | short nlink; // Number of links to file 10 | uint size; // Size of file in bytes 11 | }; 12 | -------------------------------------------------------------------------------- /xv6/stressfs.c: -------------------------------------------------------------------------------- 1 | // Demonstrate that moving the "acquire" in iderw after the loop that 2 | // appends to the idequeue results in a race. 3 | 4 | // For this to work, you should also add a spin within iderw's 5 | // idequeue traversal loop. Adding the following demonstrated a panic 6 | // after about 5 runs of stressfs in QEMU on a 2.1GHz CPU: 7 | // for (i = 0; i < 40000; i++) 8 | // asm volatile(""); 9 | 10 | #include "types.h" 11 | #include "stat.h" 12 | #include "user.h" 13 | #include "fs.h" 14 | #include "fcntl.h" 15 | 16 | int 17 | main(int argc, char *argv[]) 18 | { 19 | int fd, i; 20 | char path[] = "stressfs0"; 21 | char data[512]; 22 | 23 | printf(1, "stressfs starting\n"); 24 | memset(data, 'a', sizeof(data)); 25 | 26 | for(i = 0; i < 4; i++) 27 | if(fork() > 0) 28 | break; 29 | 30 | printf(1, "write %d\n", i); 31 | 32 | path[8] += i; 33 | fd = open(path, O_CREATE | O_RDWR); 34 | for(i = 0; i < 20; i++) 35 | // printf(fd, "%d\n", i); 36 | write(fd, data, sizeof(data)); 37 | close(fd); 38 | 39 | printf(1, "read\n"); 40 | 41 | fd = open(path, O_RDONLY); 42 | for (i = 0; i < 20; i++) 43 | read(fd, data, sizeof(data)); 44 | close(fd); 45 | 46 | wait(); 47 | 48 | exit(); 49 | } 50 | -------------------------------------------------------------------------------- /xv6/string.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "x86.h" 3 | 4 | void* 5 | memset(void *dst, int c, uint n) 6 | { 7 | if ((int)dst%4 == 0 && n%4 == 0){ 8 | c &= 0xFF; 9 | stosl(dst, (c<<24)|(c<<16)|(c<<8)|c, n/4); 10 | } else 11 | stosb(dst, c, n); 12 | return dst; 13 | } 14 | 15 | int 16 | memcmp(const void *v1, const void *v2, uint n) 17 | { 18 | const uchar *s1, *s2; 19 | 20 | s1 = v1; 21 | s2 = v2; 22 | while(n-- > 0){ 23 | if(*s1 != *s2) 24 | return *s1 - *s2; 25 | s1++, s2++; 26 | } 27 | 28 | return 0; 29 | } 30 | 31 | void* 32 | memmove(void *dst, const void *src, uint n) 33 | { 34 | const char *s; 35 | char *d; 36 | 37 | s = src; 38 | d = dst; 39 | if(s < d && s + n > d){ 40 | s += n; 41 | d += n; 42 | while(n-- > 0) 43 | *--d = *--s; 44 | } else 45 | while(n-- > 0) 46 | *d++ = *s++; 47 | 48 | return dst; 49 | } 50 | 51 | // memcpy exists to placate GCC. Use memmove. 52 | void* 53 | memcpy(void *dst, const void *src, uint n) 54 | { 55 | return memmove(dst, src, n); 56 | } 57 | 58 | int 59 | strncmp(const char *p, const char *q, uint n) 60 | { 61 | while(n > 0 && *p && *p == *q) 62 | n--, p++, q++; 63 | if(n == 0) 64 | return 0; 65 | return (uchar)*p - (uchar)*q; 66 | } 67 | 68 | char* 69 | strncpy(char *s, const char *t, int n) 70 | { 71 | char *os; 72 | 73 | os = s; 74 | while(n-- > 0 && (*s++ = *t++) != 0) 75 | ; 76 | while(n-- > 0) 77 | *s++ = 0; 78 | return os; 79 | } 80 | 81 | // Like strncpy but guaranteed to NUL-terminate. 82 | char* 83 | safestrcpy(char *s, const char *t, int n) 84 | { 85 | char *os; 86 | 87 | os = s; 88 | if(n <= 0) 89 | return os; 90 | while(--n > 0 && (*s++ = *t++) != 0) 91 | ; 92 | *s = 0; 93 | return os; 94 | } 95 | 96 | int 97 | strlen(const char *s) 98 | { 99 | int n; 100 | 101 | for(n = 0; s[n]; n++) 102 | ; 103 | return n; 104 | } 105 | 106 | -------------------------------------------------------------------------------- /xv6/swtch.S: -------------------------------------------------------------------------------- 1 | # Context switch 2 | # 3 | # void swtch(struct context **old, struct context *new); 4 | # 5 | # Save current register context in old 6 | # and then load register context from new. 7 | 8 | .globl swtch 9 | swtch: 10 | movl 4(%esp), %eax 11 | movl 8(%esp), %edx 12 | 13 | # Save old callee-save registers 14 | pushl %ebp 15 | pushl %ebx 16 | pushl %esi 17 | pushl %edi 18 | 19 | # Switch stacks 20 | movl %esp, (%eax) 21 | movl %edx, %esp 22 | 23 | # Load new callee-save registers 24 | popl %edi 25 | popl %esi 26 | popl %ebx 27 | popl %ebp 28 | ret 29 | -------------------------------------------------------------------------------- /xv6/symlink.patch: -------------------------------------------------------------------------------- 1 | diff -r f8a4e40ab1d6 fs.c 2 | --- a/fs.c Thu Aug 30 14:32:06 2007 -0400 3 | +++ b/fs.c Thu Aug 30 14:29:02 2007 -0400 4 | @@ -577,12 +577,18 @@ skipelem(char *path, char *name) 5 | // If parent != 0, return the inode for the parent and copy the final 6 | // path element into name, which must have room for DIRSIZ bytes. 7 | static struct inode* 8 | -_namei(char *path, int parent, char *name) 9 | +_namei(struct inode *root, char *path, int parent, char *name, int depth) 10 | { 11 | struct inode *ip, *next; 12 | + char buf[100], tname[DIRSIZ]; 13 | + 14 | + if(depth > 5) 15 | + return 0; 16 | 17 | if(*path == '/') 18 | ip = iget(ROOTDEV, 1); 19 | + else if(root) 20 | + ip = idup(root); 21 | else 22 | ip = idup(cp->cwd); 23 | 24 | @@ -598,10 +604,24 @@ _namei(char *path, int parent, char *nam 25 | return ip; 26 | } 27 | if((next = dirlookup(ip, name, 0)) == 0){ 28 | + cprintf("did not find %s\n", name); 29 | iunlockput(ip); 30 | return 0; 31 | } 32 | - iunlockput(ip); 33 | + iunlock(ip); 34 | + ilock(next); 35 | + if(next->type == T_SYMLINK){ 36 | + if(next->size >= sizeof(buf) || readi(next, buf, 0, next->size) != next->size){ 37 | + iunlockput(next); 38 | + iput(ip); 39 | + return 0; 40 | + } 41 | + buf[next->size] = 0; 42 | + iunlockput(next); 43 | + next = _namei(ip, buf, 0, tname, depth+1); 44 | + }else 45 | + iunlock(next); 46 | + iput(ip); 47 | ip = next; 48 | } 49 | if(parent){ 50 | @@ -615,11 +635,11 @@ namei(char *path) 51 | namei(char *path) 52 | { 53 | char name[DIRSIZ]; 54 | - return _namei(path, 0, name); 55 | + return _namei(0, path, 0, name, 0); 56 | } 57 | 58 | struct inode* 59 | nameiparent(char *path, char *name) 60 | { 61 | - return _namei(path, 1, name); 62 | -} 63 | + return _namei(0, path, 1, name, 0); 64 | +} 65 | diff -r f8a4e40ab1d6 fs.h 66 | --- a/fs.h Thu Aug 30 14:32:06 2007 -0400 67 | +++ b/fs.h Thu Aug 30 13:05:43 2007 -0400 68 | @@ -33,6 +33,7 @@ struct dinode { 69 | #define T_DIR 1 // Directory 70 | #define T_FILE 2 // File 71 | #define T_DEV 3 // Special device 72 | +#define T_SYMLINK 4 // Symlink 73 | 74 | // Inodes per block. 75 | #define IPB (BSIZE / sizeof(struct dinode)) 76 | diff -r f8a4e40ab1d6 syscall.c 77 | --- a/syscall.c Thu Aug 30 14:32:06 2007 -0400 78 | +++ b/syscall.c Thu Aug 30 13:05:29 2007 -0400 79 | @@ -96,6 +96,7 @@ extern int sys_unlink(void); 80 | extern int sys_unlink(void); 81 | extern int sys_wait(void); 82 | extern int sys_write(void); 83 | +extern int sys_symlink(void); 84 | 85 | static int (*syscalls[])(void) = { 86 | [SYS_chdir] sys_chdir, 87 | @@ -118,6 +119,7 @@ static int (*syscalls[])(void) = { 88 | [SYS_unlink] sys_unlink, 89 | [SYS_wait] sys_wait, 90 | [SYS_write] sys_write, 91 | +[SYS_symlink] sys_symlink, 92 | }; 93 | 94 | void 95 | diff -r f8a4e40ab1d6 syscall.h 96 | --- a/syscall.h Thu Aug 30 14:32:06 2007 -0400 97 | +++ b/syscall.h Thu Aug 30 13:02:48 2007 -0400 98 | @@ -19,3 +19,4 @@ 99 | #define SYS_getpid 18 100 | #define SYS_sbrk 19 101 | #define SYS_sleep 20 102 | +#define SYS_symlink 21 103 | diff -r f8a4e40ab1d6 sysfile.c 104 | --- a/sysfile.c Thu Aug 30 14:32:06 2007 -0400 105 | +++ b/sysfile.c Thu Aug 30 13:10:31 2007 -0400 106 | @@ -257,6 +257,21 @@ create(char *path, int canexist, short t 107 | } 108 | 109 | int 110 | +sys_symlink(void) 111 | +{ 112 | + char *old, *new; 113 | + struct inode *ip; 114 | + 115 | + if(argstr(0, &old) < 0 || argstr(1, &new) < 0) 116 | + return -1; 117 | + if((ip = create(new, 0, T_SYMLINK, 0, 0)) == 0) 118 | + return -1; 119 | + writei(ip, old, 0, strlen(old)); 120 | + iunlockput(ip); 121 | + return 0; 122 | +} 123 | + 124 | +int 125 | sys_open(void) 126 | { 127 | char *path; 128 | @@ -393,3 +408,4 @@ sys_pipe(void) 129 | fd[1] = fd1; 130 | return 0; 131 | } 132 | + 133 | diff -r f8a4e40ab1d6 user.h 134 | --- a/user.h Thu Aug 30 14:32:06 2007 -0400 135 | +++ b/user.h Thu Aug 30 13:02:34 2007 -0400 136 | @@ -21,6 +21,7 @@ int getpid(); 137 | int getpid(); 138 | char* sbrk(int); 139 | int sleep(int); 140 | +int symlink(int); 141 | 142 | // ulib.c 143 | int stat(char*, struct stat*); 144 | diff -r f8a4e40ab1d6 usys.S 145 | --- a/usys.S Thu Aug 30 14:32:06 2007 -0400 146 | +++ b/usys.S Thu Aug 30 13:05:54 2007 -0400 147 | @@ -28,3 +28,4 @@ STUB(getpid) 148 | STUB(getpid) 149 | STUB(sbrk) 150 | STUB(sleep) 151 | +STUB(symlink) 152 | -------------------------------------------------------------------------------- /xv6/syscall.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "defs.h" 3 | #include "param.h" 4 | #include "memlayout.h" 5 | #include "mmu.h" 6 | #include "proc.h" 7 | #include "x86.h" 8 | #include "syscall.h" 9 | 10 | // User code makes a system call with INT T_SYSCALL. 11 | // System call number in %eax. 12 | // Arguments on the stack, from the user call to the C 13 | // library system call function. The saved user %esp points 14 | // to a saved program counter, and then the first argument. 15 | 16 | // Fetch the int at addr from the current process. 17 | int 18 | fetchint(uint addr, int *ip) 19 | { 20 | if(addr >= proc->sz || addr+4 > proc->sz) 21 | return -1; 22 | *ip = *(int*)(addr); 23 | return 0; 24 | } 25 | 26 | // Fetch the nul-terminated string at addr from the current process. 27 | // Doesn't actually copy the string - just sets *pp to point at it. 28 | // Returns length of string, not including nul. 29 | int 30 | fetchstr(uint addr, char **pp) 31 | { 32 | char *s, *ep; 33 | 34 | if(addr >= proc->sz) 35 | return -1; 36 | *pp = (char*)addr; 37 | ep = (char*)proc->sz; 38 | for(s = *pp; s < ep; s++) 39 | if(*s == 0) 40 | return s - *pp; 41 | return -1; 42 | } 43 | 44 | // Fetch the nth 32-bit system call argument. 45 | int 46 | argint(int n, int *ip) 47 | { 48 | return fetchint(proc->tf->esp + 4 + 4*n, ip); 49 | } 50 | 51 | // Fetch the nth word-sized system call argument as a pointer 52 | // to a block of memory of size n bytes. Check that the pointer 53 | // lies within the process address space. 54 | int 55 | argptr(int n, char **pp, int size) 56 | { 57 | int i; 58 | 59 | if(argint(n, &i) < 0) 60 | return -1; 61 | if((uint)i >= proc->sz || (uint)i+size > proc->sz) 62 | return -1; 63 | *pp = (char*)i; 64 | return 0; 65 | } 66 | 67 | // Fetch the nth word-sized system call argument as a string pointer. 68 | // Check that the pointer is valid and the string is nul-terminated. 69 | // (There is no shared writable memory, so the string can't change 70 | // between this check and being used by the kernel.) 71 | int 72 | argstr(int n, char **pp) 73 | { 74 | int addr; 75 | if(argint(n, &addr) < 0) 76 | return -1; 77 | return fetchstr(addr, pp); 78 | } 79 | 80 | extern int sys_chdir(void); 81 | extern int sys_close(void); 82 | extern int sys_dup(void); 83 | extern int sys_exec(void); 84 | extern int sys_exit(void); 85 | extern int sys_fork(void); 86 | extern int sys_fstat(void); 87 | extern int sys_getpid(void); 88 | extern int sys_kill(void); 89 | extern int sys_link(void); 90 | extern int sys_mkdir(void); 91 | extern int sys_mknod(void); 92 | extern int sys_open(void); 93 | extern int sys_pipe(void); 94 | extern int sys_read(void); 95 | extern int sys_sbrk(void); 96 | extern int sys_sleep(void); 97 | extern int sys_unlink(void); 98 | extern int sys_wait(void); 99 | extern int sys_write(void); 100 | extern int sys_kwrite(void); 101 | extern int sys_uptime(void); 102 | extern int sys_getMsg(void); 103 | extern int sys_createWindow(void); 104 | extern int sys_destroyWindow(void); 105 | extern int sys_updateWindow(void); 106 | extern int sys_updatePartialWindow(void); 107 | extern int sys_setSampleRate(void); 108 | extern int sys_pause(void); 109 | extern int sys_wavdecode(void); 110 | extern int sys_waitForDecode(void); 111 | extern int sys_beginDecode(void); 112 | extern int sys_endDecode(void); 113 | extern int sys_getCoreBuf(void); 114 | 115 | static int (*syscalls[])(void) = { 116 | [SYS_fork] sys_fork, 117 | [SYS_exit] sys_exit, 118 | [SYS_wait] sys_wait, 119 | [SYS_pipe] sys_pipe, 120 | [SYS_read] sys_read, 121 | [SYS_kill] sys_kill, 122 | [SYS_exec] sys_exec, 123 | [SYS_fstat] sys_fstat, 124 | [SYS_chdir] sys_chdir, 125 | [SYS_dup] sys_dup, 126 | [SYS_getpid] sys_getpid, 127 | [SYS_sbrk] sys_sbrk, 128 | [SYS_sleep] sys_sleep, 129 | [SYS_uptime] sys_uptime, 130 | [SYS_open] sys_open, 131 | [SYS_write] sys_write, 132 | [SYS_mknod] sys_mknod, 133 | [SYS_unlink] sys_unlink, 134 | [SYS_link] sys_link, 135 | [SYS_mkdir] sys_mkdir, 136 | [SYS_close] sys_close, 137 | [SYS_getMsg] sys_getMsg, 138 | [SYS_createWindow] sys_createWindow, 139 | [SYS_destroyWindow] sys_destroyWindow, 140 | [SYS_updateWindow] sys_updateWindow, 141 | [SYS_updatePartialWindow] sys_updatePartialWindow, 142 | [SYS_kwrite] sys_kwrite, 143 | [SYS_setSampleRate] sys_setSampleRate, 144 | [SYS_pause] sys_pause, 145 | [SYS_wavdecode] sys_wavdecode, 146 | [SYS_beginDecode] sys_beginDecode, 147 | [SYS_waitForDecode] sys_waitForDecode, 148 | [SYS_endDecode] sys_endDecode, 149 | [SYS_getCoreBuf] sys_getCoreBuf, 150 | }; 151 | 152 | void 153 | syscall(void) 154 | { 155 | int num; 156 | 157 | num = proc->tf->eax; 158 | if(num > 0 && num < NELEM(syscalls) && syscalls[num]) { 159 | proc->tf->eax = syscalls[num](); 160 | } else { 161 | cprintf("%d %s: unknown sys call %d\n", 162 | proc->pid, proc->name, num); 163 | proc->tf->eax = -1; 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /xv6/syscall.h: -------------------------------------------------------------------------------- 1 | // System call numbers 2 | #define SYS_fork 1 3 | #define SYS_exit 2 4 | #define SYS_wait 3 5 | #define SYS_pipe 4 6 | #define SYS_read 5 7 | #define SYS_kill 6 8 | #define SYS_exec 7 9 | #define SYS_fstat 8 10 | #define SYS_chdir 9 11 | #define SYS_dup 10 12 | #define SYS_getpid 11 13 | #define SYS_sbrk 12 14 | #define SYS_sleep 13 15 | #define SYS_uptime 14 16 | #define SYS_open 15 17 | #define SYS_write 16 18 | #define SYS_mknod 17 19 | #define SYS_unlink 18 20 | #define SYS_link 19 21 | #define SYS_mkdir 20 22 | #define SYS_close 21 23 | #define SYS_getMsg 22 24 | #define SYS_createWindow 23 25 | #define SYS_destroyWindow 24 26 | #define SYS_updateWindow 25 27 | #define SYS_updatePartialWindow 26 28 | #define SYS_setSampleRate 27 29 | #define SYS_kwrite 28 30 | #define SYS_pause 29 31 | #define SYS_wavdecode 30 32 | #define SYS_beginDecode 31 33 | #define SYS_waitForDecode 32 34 | #define SYS_endDecode 33 35 | #define SYS_getCoreBuf 34 36 | -------------------------------------------------------------------------------- /xv6/sysmp3.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/sysmp3.c -------------------------------------------------------------------------------- /xv6/sysproc.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "x86.h" 3 | #include "defs.h" 4 | #include "date.h" 5 | #include "param.h" 6 | #include "memlayout.h" 7 | #include "mmu.h" 8 | #include "proc.h" 9 | int 10 | sys_fork(void) 11 | { 12 | return fork(); 13 | } 14 | 15 | int 16 | sys_exit(void) 17 | { 18 | exit(); 19 | return 0; // not reached 20 | } 21 | 22 | int 23 | sys_wait(void) 24 | { 25 | return wait(); 26 | } 27 | 28 | int 29 | sys_kill(void) 30 | { 31 | int pid; 32 | 33 | if(argint(0, &pid) < 0) 34 | return -1; 35 | return kill(pid); 36 | } 37 | 38 | int 39 | sys_getpid(void) 40 | { 41 | return proc->pid; 42 | } 43 | 44 | int 45 | sys_sbrk(void) 46 | { 47 | int addr; 48 | int n; 49 | 50 | if(argint(0, &n) < 0) 51 | return -1; 52 | addr = proc->sz; 53 | if(growproc(n) < 0) 54 | return -1; 55 | return addr; 56 | } 57 | 58 | int 59 | sys_sleep(void) 60 | { 61 | int n; 62 | uint ticks0; 63 | 64 | if(argint(0, &n) < 0) 65 | return -1; 66 | acquire(&tickslock); 67 | ticks0 = ticks; 68 | while(ticks - ticks0 < n){ 69 | if(proc->killed){ 70 | release(&tickslock); 71 | return -1; 72 | } 73 | sleep(&ticks, &tickslock); 74 | } 75 | release(&tickslock); 76 | return 0; 77 | } 78 | 79 | // return how many clock tick interrupts have occurred 80 | // since start. 81 | int 82 | sys_uptime(void) 83 | { 84 | uint xticks; 85 | 86 | acquire(&tickslock); 87 | xticks = ticks; 88 | release(&tickslock); 89 | return xticks; 90 | } 91 | -------------------------------------------------------------------------------- /xv6/syswindow.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "defs.h" 3 | #include "param.h" 4 | #include "mmu.h" 5 | #include "proc.h" 6 | #include "window.h" 7 | 8 | int sys_createWindow() 9 | { 10 | int left_x, right_x, left_y, right_y; 11 | if (argint(0, &left_x) < 0 || argint(1, &left_y) < 0 || argint(2, &right_x) < 0 || argint(3, &right_y) < 0) 12 | return -1; 13 | return allocWindow(left_x, left_y, right_x, right_y, proc->pid)->window_id; 14 | } 15 | 16 | int sys_destroyWindow() 17 | { 18 | int window_id; 19 | if (argint(0, &window_id) < 0) 20 | return -1; 21 | return releaseWindow(window_id); 22 | } 23 | 24 | int sys_updateWindow() 25 | { 26 | int window_id; 27 | int detail; 28 | color16* context; 29 | WindowLink pWindow; 30 | if (argint(0, &window_id) < 0) 31 | return -1; 32 | pWindow = getWindowById(window_id); 33 | //cprintf("updateWindow called: %d\n", pWindow); 34 | if (pWindow == 0) return -1; 35 | int size = ((pWindow->window_position).right_x - (pWindow->window_position).left_x) * 36 | ((pWindow->window_position).right_y - (pWindow->window_position).left_y); 37 | //cprintf("window size: %d\n", size); 38 | if (size < 0) return -1; 39 | if (argptr(1, (void*)&context, sizeof(color16) * size) < 0) return -1; 40 | if (argint(2, &detail) < 0) return -1; 41 | drawWindow(pWindow, context, detail); 42 | return 0; 43 | } 44 | 45 | int sys_updatePartialWindow() 46 | { 47 | int window_id; 48 | int x1, y1, x2, y2; 49 | color16* context; 50 | WindowLink pWindow; 51 | if (argint(0, &window_id) < 0) 52 | return -1; 53 | pWindow = getWindowById(window_id); 54 | if (pWindow == 0) return -1; 55 | int size = ((pWindow->window_position).right_x - (pWindow->window_position).left_x) * 56 | ((pWindow->window_position).right_y - (pWindow->window_position).left_y); 57 | //cprintf("window size: %d\n", size); 58 | if (size < 0) return -1; 59 | 60 | if (argptr(1, (void*)&context, sizeof(color16) * size) < 0) 61 | return -1; 62 | if (argint(2, &x1) < 0 || argint(3, &y1) < 0 || argint(4, &x2) < 0 || argint(5, &y2) < 0) 63 | return -1; 64 | drawArea(pWindow, context, x1, y1, x2, y2); 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /xv6/tags: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/tags -------------------------------------------------------------------------------- /xv6/test.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/test.wav -------------------------------------------------------------------------------- /xv6/text.c: -------------------------------------------------------------------------------- 1 | #include "defs.h" 2 | 3 | 4 | -------------------------------------------------------------------------------- /xv6/timer.c: -------------------------------------------------------------------------------- 1 | // Intel 8253/8254/82C54 Programmable Interval Timer (PIT). 2 | // Only used on uniprocessors; 3 | // SMP machines use the local APIC timer. 4 | 5 | #include "types.h" 6 | #include "defs.h" 7 | #include "traps.h" 8 | #include "x86.h" 9 | 10 | #define IO_TIMER1 0x040 // 8253 Timer #1 11 | 12 | // Frequency of all three count-down timers; 13 | // (TIMER_FREQ/freq) is the appropriate count 14 | // to generate a frequency of freq Hz. 15 | 16 | #define TIMER_FREQ 1193182 17 | #define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x)) 18 | 19 | #define TIMER_MODE (IO_TIMER1 + 3) // timer mode port 20 | #define TIMER_SEL0 0x00 // select counter 0 21 | #define TIMER_RATEGEN 0x04 // mode 2, rate generator 22 | #define TIMER_16BIT 0x30 // r/w counter 16 bits, LSB first 23 | 24 | void 25 | timerinit(void) 26 | { 27 | // Interrupt 100 times/sec. 28 | outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 29 | outb(IO_TIMER1, TIMER_DIV(100) % 256); 30 | outb(IO_TIMER1, TIMER_DIV(100) / 256); 31 | picenable(IRQ_TIMER); 32 | } 33 | -------------------------------------------------------------------------------- /xv6/toc.ftr: -------------------------------------------------------------------------------- 1 | 2 | 3 | The source listing is preceded by a cross-reference that lists every defined 4 | constant, struct, global variable, and function in xv6. Each entry gives, 5 | on the same line as the name, the line number (or, in a few cases, numbers) 6 | where the name is defined. Successive lines in an entry list the line 7 | numbers where the name is used. For example, this entry: 8 | 9 | swtch 2658 10 | 0374 2428 2466 2657 2658 11 | 12 | indicates that swtch is defined on line 2658 and is mentioned on five lines 13 | on sheets 03, 24, and 26. 14 | -------------------------------------------------------------------------------- /xv6/toc.hdr: -------------------------------------------------------------------------------- 1 | The numbers to the left of the file names in the table are sheet numbers. 2 | The source code has been printed in a double column format with fifty 3 | lines per column, giving one hundred lines per sheet (or page). 4 | Thus there is a convenient relationship between line numbers and sheet numbers. 5 | 6 | 7 | -------------------------------------------------------------------------------- /xv6/touch.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | #include "fcntl.h" 5 | 6 | int 7 | main(int argc, char *argv[]) 8 | { 9 | if (argc <= 1) { 10 | printf(1, "Please input this command as [touch file_name1 file_name2 ...]\n"); 11 | } 12 | 13 | int i, count = 0; 14 | for (i = 1; i < argc; i++) { 15 | int fd; 16 | // 测试文件是否存在 17 | if ((fd = open(argv[i], O_RDONLY)) < 0) { 18 | // 文件不存在就创建它 19 | fd = open(argv[i], O_CREATE|O_RDONLY); 20 | count++; 21 | } 22 | close(fd); 23 | } 24 | 25 | printf(1, "%d file(s) created, %d file(s) skiped.\n", count, argc - 1 - count); 26 | 27 | exit(); 28 | } -------------------------------------------------------------------------------- /xv6/trap.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "defs.h" 3 | #include "param.h" 4 | #include "memlayout.h" 5 | #include "mmu.h" 6 | #include "proc.h" 7 | #include "x86.h" 8 | #include "traps.h" 9 | #include "spinlock.h" 10 | 11 | // Interrupt descriptor table (shared by all CPUs). 12 | struct gatedesc idt[256]; 13 | extern uint vectors[]; // in vectors.S: array of 256 entry pointers 14 | struct spinlock tickslock; 15 | uint ticks; 16 | 17 | void 18 | tvinit(void) 19 | { 20 | int i; 21 | 22 | for(i = 0; i < 256; i++) 23 | SETGATE(idt[i], 0, SEG_KCODE<<3, vectors[i], 0); 24 | SETGATE(idt[T_SYSCALL], 1, SEG_KCODE<<3, vectors[T_SYSCALL], DPL_USER); 25 | 26 | initlock(&tickslock, "time"); 27 | } 28 | 29 | void 30 | idtinit(void) 31 | { 32 | lidt(idt, sizeof(idt)); 33 | } 34 | 35 | //PAGEBREAK: 41 36 | void 37 | trap(struct trapframe *tf) 38 | { 39 | if(tf->trapno == T_SYSCALL){ 40 | if(proc->killed) 41 | exit(); 42 | proc->tf = tf; 43 | syscall(); 44 | if(proc->killed) 45 | exit(); 46 | return; 47 | } 48 | 49 | switch(tf->trapno){ 50 | case T_IRQ0 + IRQ_TIMER: 51 | if(cpu->id == 0){ 52 | acquire(&tickslock); 53 | ticks++; 54 | wakeup(&ticks); 55 | release(&tickslock); 56 | } 57 | lapiceoi(); 58 | break; 59 | case T_IRQ0 + IRQ_SOUND: 60 | soundInterrupt(); 61 | lapiceoi(); 62 | break; 63 | case T_IRQ0 + IRQ_IDE: 64 | ideintr(); 65 | lapiceoi(); 66 | break; 67 | case T_IRQ0 + IRQ_IDE+1: 68 | // Bochs generates spurious IDE1 interrupts. 69 | break; 70 | case T_IRQ0 + IRQ_KBD: 71 | kbdintr(); 72 | lapiceoi(); 73 | break; 74 | case T_IRQ0 + IRQ_COM1: 75 | uartintr(); 76 | lapiceoi(); 77 | break; 78 | //mouse trap 79 | case T_IRQ0 + IRQ_MOUS: 80 | mouseintr(ticks); 81 | lapiceoi(); 82 | break; 83 | case T_IRQ0 + 7: 84 | case T_IRQ0 + IRQ_SPURIOUS: 85 | cprintf("cpu%d: spurious interrupt at %x:%x\n", 86 | cpu->id, tf->cs, tf->eip); 87 | lapiceoi(); 88 | break; 89 | 90 | //PAGEBREAK: 13 91 | default: 92 | if(proc == 0 || (tf->cs&3) == 0){ 93 | // In kernel, it must be our mistake. 94 | cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n", 95 | tf->trapno, cpu->id, tf->eip, rcr2()); 96 | panic("trap"); 97 | } 98 | // In user space, assume process misbehaved. 99 | cprintf("pid %d %s: trap %d err %d on cpu %d " 100 | "eip 0x%x addr 0x%x--kill proc\n", 101 | proc->pid, proc->name, tf->trapno, tf->err, cpu->id, tf->eip, 102 | rcr2()); 103 | proc->killed = 1; 104 | } 105 | 106 | // Force process exit if it has been killed and is in user space. 107 | // (If it is still executing in the kernel, let it keep running 108 | // until it gets to the regular system call return.) 109 | if(proc && proc->killed && (tf->cs&3) == DPL_USER) 110 | exit(); 111 | 112 | // Force process to give up CPU on clock tick. 113 | // If interrupts were on while locks held, would need to check nlock. 114 | if(proc && proc->state == RUNNING && tf->trapno == T_IRQ0+IRQ_TIMER) 115 | yield(); 116 | 117 | // Check if the process has been killed since we yielded 118 | if(proc && proc->killed && (tf->cs&3) == DPL_USER) 119 | exit(); 120 | } 121 | -------------------------------------------------------------------------------- /xv6/trapasm.S: -------------------------------------------------------------------------------- 1 | #include "mmu.h" 2 | 3 | # vectors.S sends all traps here. 4 | .globl alltraps 5 | alltraps: 6 | # Build trap frame. 7 | pushl %ds 8 | pushl %es 9 | pushl %fs 10 | pushl %gs 11 | pushal 12 | 13 | # Set up data and per-cpu segments. 14 | movw $(SEG_KDATA<<3), %ax 15 | movw %ax, %ds 16 | movw %ax, %es 17 | movw $(SEG_KCPU<<3), %ax 18 | movw %ax, %fs 19 | movw %ax, %gs 20 | 21 | # Call trap(tf), where tf=%esp 22 | pushl %esp 23 | call trap 24 | addl $4, %esp 25 | 26 | # Return falls through to trapret... 27 | .globl trapret 28 | trapret: 29 | popal 30 | popl %gs 31 | popl %fs 32 | popl %es 33 | popl %ds 34 | addl $0x8, %esp # trapno and errcode 35 | iret 36 | -------------------------------------------------------------------------------- /xv6/traps.h: -------------------------------------------------------------------------------- 1 | // x86 trap and interrupt constants. 2 | 3 | // Processor-defined: 4 | #define T_DIVIDE 0 // divide error 5 | #define T_DEBUG 1 // debug exception 6 | #define T_NMI 2 // non-maskable interrupt 7 | #define T_BRKPT 3 // breakpoint 8 | #define T_OFLOW 4 // overflow 9 | #define T_BOUND 5 // bounds check 10 | #define T_ILLOP 6 // illegal opcode 11 | #define T_DEVICE 7 // device not available 12 | #define T_DBLFLT 8 // double fault 13 | // #define T_COPROC 9 // reserved (not used since 486) 14 | #define T_TSS 10 // invalid task switch segment 15 | #define T_SEGNP 11 // segment not present 16 | #define T_STACK 12 // stack exception 17 | #define T_GPFLT 13 // general protection fault 18 | #define T_PGFLT 14 // page fault 19 | // #define T_RES 15 // reserved 20 | #define T_FPERR 16 // floating point error 21 | #define T_ALIGN 17 // aligment check 22 | #define T_MCHK 18 // machine check 23 | #define T_SIMDERR 19 // SIMD floating point error 24 | 25 | // These are arbitrarily chosen, but with care not to overlap 26 | // processor defined exceptions or interrupt vectors. 27 | #define T_SYSCALL 64 // system call 28 | #define T_DEFAULT 500 // catchall 29 | 30 | #define T_IRQ0 32 // IRQ 0 corresponds to int T_IRQ 31 | 32 | #define IRQ_TIMER 0 33 | #define IRQ_KBD 1 34 | #define IRQ_COM1 4 35 | #define IRQ_SOUND 11 36 | #define IRQ_MOUS 12 37 | #define IRQ_IDE 14 38 | #define IRQ_ERROR 19 39 | #define IRQ_SPURIOUS 31 40 | 41 | -------------------------------------------------------------------------------- /xv6/trash.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/trash.bmp -------------------------------------------------------------------------------- /xv6/types.h: -------------------------------------------------------------------------------- 1 | typedef unsigned int uint; 2 | typedef unsigned short ushort; 3 | typedef unsigned char uchar; 4 | typedef uint pde_t; 5 | -------------------------------------------------------------------------------- /xv6/uart.c: -------------------------------------------------------------------------------- 1 | // Intel 8250 serial port (UART). 2 | 3 | #include "types.h" 4 | #include "defs.h" 5 | #include "param.h" 6 | #include "traps.h" 7 | #include "spinlock.h" 8 | #include "fs.h" 9 | #include "file.h" 10 | #include "mmu.h" 11 | #include "proc.h" 12 | #include "x86.h" 13 | 14 | #define COM1 0x3f8 15 | 16 | static int uart; // is there a uart? 17 | 18 | void 19 | uartinit(void) 20 | { 21 | char *p; 22 | 23 | // Turn off the FIFO 24 | outb(COM1+2, 0); 25 | 26 | // 9600 baud, 8 data bits, 1 stop bit, parity off. 27 | outb(COM1+3, 0x80); // Unlock divisor 28 | outb(COM1+0, 115200/9600); 29 | outb(COM1+1, 0); 30 | outb(COM1+3, 0x03); // Lock divisor, 8 data bits. 31 | outb(COM1+4, 0); 32 | outb(COM1+1, 0x01); // Enable receive interrupts. 33 | 34 | // If status is 0xFF, no serial port. 35 | if(inb(COM1+5) == 0xFF) 36 | return; 37 | uart = 1; 38 | 39 | // Acknowledge pre-existing interrupt conditions; 40 | // enable interrupts. 41 | inb(COM1+2); 42 | inb(COM1+0); 43 | picenable(IRQ_COM1); 44 | ioapicenable(IRQ_COM1, 0); 45 | 46 | // Announce that we're here. 47 | for(p="xv6...\n"; *p; p++) 48 | uartputc(*p); 49 | } 50 | 51 | void 52 | uartputc(int c) 53 | { 54 | int i; 55 | 56 | if(!uart) 57 | return; 58 | for(i = 0; i < 128 && !(inb(COM1+5) & 0x20); i++) 59 | microdelay(10); 60 | outb(COM1+0, c); 61 | } 62 | 63 | static int 64 | uartgetc(void) 65 | { 66 | if(!uart) 67 | return -1; 68 | if(!(inb(COM1+5) & 0x01)) 69 | return -1; 70 | return inb(COM1+0); 71 | } 72 | 73 | void 74 | uartintr(void) 75 | { 76 | consoleintr(uartgetc, 0); 77 | } 78 | -------------------------------------------------------------------------------- /xv6/ulib.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "fcntl.h" 4 | #include "user.h" 5 | #include "x86.h" 6 | 7 | char* 8 | strcpy(char *s, char *t) 9 | { 10 | char *os; 11 | 12 | os = s; 13 | while((*s++ = *t++) != 0) 14 | ; 15 | return os; 16 | } 17 | 18 | int 19 | strcmp(const char *p, const char *q) 20 | { 21 | while(*p && *p == *q) 22 | p++, q++; 23 | return (uchar)*p - (uchar)*q; 24 | } 25 | 26 | uint 27 | strlen(char *s) 28 | { 29 | int n; 30 | 31 | for(n = 0; s[n]; n++) 32 | ; 33 | return n; 34 | } 35 | 36 | void* 37 | memset(void *dst, int c, uint n) 38 | { 39 | stosb(dst, c, n); 40 | return dst; 41 | } 42 | 43 | char* 44 | strchr(const char *s, char c) 45 | { 46 | for(; *s; s++) 47 | if(*s == c) 48 | return (char*)s; 49 | return 0; 50 | } 51 | 52 | char* 53 | gets(char *buf, int max) 54 | { 55 | int i, cc; 56 | char c; 57 | 58 | for(i=0; i+1 < max; ){ 59 | cc = read(0, &c, 1); 60 | if(cc < 1) 61 | break; 62 | buf[i++] = c; 63 | if(c == '\n' || c == '\r') 64 | break; 65 | } 66 | buf[i] = '\0'; 67 | return buf; 68 | } 69 | 70 | int 71 | stat(char *n, struct stat *st) 72 | { 73 | int fd; 74 | int r; 75 | 76 | fd = open(n, O_RDONLY); 77 | if(fd < 0) 78 | return -1; 79 | r = fstat(fd, st); 80 | close(fd); 81 | return r; 82 | } 83 | 84 | int 85 | atoi(const char *s) 86 | { 87 | int n; 88 | 89 | n = 0; 90 | while('0' <= *s && *s <= '9') 91 | n = n*10 + *s++ - '0'; 92 | return n; 93 | } 94 | 95 | void* 96 | memmove(void *vdst, void *vsrc, int n) 97 | { 98 | char *dst, *src; 99 | 100 | dst = vdst; 101 | src = vsrc; 102 | while(n-- > 0) 103 | *dst++ = *src++; 104 | return vdst; 105 | } 106 | -------------------------------------------------------------------------------- /xv6/umalloc.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | #include "param.h" 5 | 6 | // Memory allocator by Kernighan and Ritchie, 7 | // The C programming Language, 2nd ed. Section 8.7. 8 | 9 | typedef long Align; 10 | 11 | union header { 12 | struct { 13 | union header *ptr; 14 | uint size; 15 | } s; 16 | Align x; 17 | }; 18 | 19 | typedef union header Header; 20 | 21 | static Header base; 22 | static Header *freep; 23 | 24 | void 25 | free(void *ap) 26 | { 27 | Header *bp, *p; 28 | 29 | bp = (Header*)ap - 1; 30 | for(p = freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr) 31 | if(p >= p->s.ptr && (bp > p || bp < p->s.ptr)) 32 | break; 33 | if(bp + bp->s.size == p->s.ptr){ 34 | bp->s.size += p->s.ptr->s.size; 35 | bp->s.ptr = p->s.ptr->s.ptr; 36 | } else 37 | bp->s.ptr = p->s.ptr; 38 | if(p + p->s.size == bp){ 39 | p->s.size += bp->s.size; 40 | p->s.ptr = bp->s.ptr; 41 | } else 42 | p->s.ptr = bp; 43 | freep = p; 44 | } 45 | 46 | static Header* 47 | morecore(uint nu) 48 | { 49 | char *p; 50 | Header *hp; 51 | 52 | if(nu < 4096) 53 | nu = 4096; 54 | p = sbrk(nu * sizeof(Header)); 55 | if(p == (char*)-1) 56 | return 0; 57 | hp = (Header*)p; 58 | hp->s.size = nu; 59 | free((void*)(hp + 1)); 60 | return freep; 61 | } 62 | 63 | void* 64 | malloc(uint nbytes) 65 | { 66 | Header *p, *prevp; 67 | uint nunits; 68 | 69 | nunits = (nbytes + sizeof(Header) - 1)/sizeof(Header) + 1; 70 | if((prevp = freep) == 0){ 71 | base.s.ptr = freep = prevp = &base; 72 | base.s.size = 0; 73 | } 74 | for(p = prevp->s.ptr; ; prevp = p, p = p->s.ptr){ 75 | if(p->s.size >= nunits){ 76 | if(p->s.size == nunits) 77 | prevp->s.ptr = p->s.ptr; 78 | else { 79 | p->s.size -= nunits; 80 | p += p->s.size; 81 | p->s.size = nunits; 82 | } 83 | freep = prevp; 84 | return (void*)(p + 1); 85 | } 86 | if(p == freep) 87 | if((p = morecore(nunits)) == 0) 88 | return 0; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /xv6/up.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/up.bmp -------------------------------------------------------------------------------- /xv6/up1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/up1.bmp -------------------------------------------------------------------------------- /xv6/uptime.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | #include "fcntl.h" 5 | 6 | int main() 7 | { 8 | int result = uptime() * 1.5; 9 | int hour = result / 360000; 10 | int minute = (result % 360000) / 6000; 11 | int second = (result % 6000) / 100; 12 | int point1 = (result % 100) / 10; 13 | int point2 = result % 10; 14 | printf(1, "the system has run %d hours %d minutes %d.%d%d seconds\n", hour, minute, second, point1, point2); 15 | exit(); 16 | } 17 | -------------------------------------------------------------------------------- /xv6/user.h: -------------------------------------------------------------------------------- 1 | struct stat; 2 | struct rtcdate; 3 | struct Msg; 4 | 5 | // system calls 6 | int fork(void); 7 | int exit(void) __attribute__((noreturn)); 8 | int wait(void); 9 | int pipe(int*); 10 | int kwrite(void*, int); 11 | int write(int, void*, int); 12 | int read(int, void*, int); 13 | int close(int); 14 | int kill(int); 15 | int exec(char*, char**); 16 | int open(char*, int); 17 | int mknod(char*, short, short); 18 | int unlink(char*); 19 | int fstat(int fd, struct stat*); 20 | int link(char*, char*); 21 | int mkdir(char*); 22 | int chdir(char*); 23 | int dup(int); 24 | int getpid(void); 25 | char* sbrk(int); 26 | int sleep(int); 27 | int uptime(void); 28 | int getMsg(struct Msg*); 29 | int createWindow(int, int, int, int); 30 | int destroyWindow(int); 31 | int updateWindow(int, unsigned short*, int); 32 | int updatePartialWindow(int, unsigned short*, int, int, int, int); 33 | int setSampleRate(int); 34 | int pause(); 35 | int wavdecode(); 36 | int beginDecode(); 37 | int waitForDecode(); 38 | int endDecode(); 39 | int getCoreBuf(); 40 | 41 | // ulib.c 42 | int stat(char*, struct stat*); 43 | char* strcpy(char*, char*); 44 | void *memmove(void*, void*, int); 45 | char* strchr(const char*, char c); 46 | int strcmp(const char*, const char*); 47 | void printf(int, char*, ...); 48 | char* gets(char*, int max); 49 | uint strlen(char*); 50 | void* memset(void*, int, uint); 51 | void* malloc(uint); 52 | void free(void*); 53 | int atoi(const char*); 54 | -------------------------------------------------------------------------------- /xv6/usys.S: -------------------------------------------------------------------------------- 1 | #include "syscall.h" 2 | #include "traps.h" 3 | 4 | #define SYSCALL(name) \ 5 | .globl name; \ 6 | name: \ 7 | movl $SYS_ ## name, %eax; \ 8 | int $T_SYSCALL; \ 9 | ret 10 | 11 | SYSCALL(fork) 12 | SYSCALL(exit) 13 | SYSCALL(wait) 14 | SYSCALL(pipe) 15 | SYSCALL(read) 16 | SYSCALL(write) 17 | SYSCALL(close) 18 | SYSCALL(kill) 19 | SYSCALL(exec) 20 | SYSCALL(open) 21 | SYSCALL(mknod) 22 | SYSCALL(unlink) 23 | SYSCALL(fstat) 24 | SYSCALL(link) 25 | SYSCALL(mkdir) 26 | SYSCALL(chdir) 27 | SYSCALL(dup) 28 | SYSCALL(getpid) 29 | SYSCALL(sbrk) 30 | SYSCALL(sleep) 31 | SYSCALL(uptime) 32 | SYSCALL(getMsg) 33 | SYSCALL(createWindow) 34 | SYSCALL(destroyWindow) 35 | SYSCALL(updateWindow) 36 | SYSCALL(updatePartialWindow) 37 | SYSCALL(kwrite) 38 | SYSCALL(setSampleRate) 39 | SYSCALL(pause) 40 | SYSCALL(wavdecode) 41 | SYSCALL(beginDecode) 42 | SYSCALL(waitForDecode) 43 | SYSCALL(endDecode) 44 | SYSCALL(getCoreBuf) -------------------------------------------------------------------------------- /xv6/vectors.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # Generate vectors.S, the trap/interrupt entry points. 4 | # There has to be one entry point per interrupt number 5 | # since otherwise there's no way for trap() to discover 6 | # the interrupt number. 7 | 8 | print "# generated by vectors.pl - do not edit\n"; 9 | print "# handlers\n"; 10 | print ".globl alltraps\n"; 11 | for(my $i = 0; $i < 256; $i++){ 12 | print ".globl vector$i\n"; 13 | print "vector$i:\n"; 14 | if(!($i == 8 || ($i >= 10 && $i <= 14) || $i == 17)){ 15 | print " pushl \$0\n"; 16 | } 17 | print " pushl \$$i\n"; 18 | print " jmp alltraps\n"; 19 | } 20 | 21 | print "\n# vector table\n"; 22 | print ".data\n"; 23 | print ".globl vectors\n"; 24 | print "vectors:\n"; 25 | for(my $i = 0; $i < 256; $i++){ 26 | print " .long vector$i\n"; 27 | } 28 | 29 | # sample output: 30 | # # handlers 31 | # .globl alltraps 32 | # .globl vector0 33 | # vector0: 34 | # pushl $0 35 | # pushl $0 36 | # jmp alltraps 37 | # ... 38 | # 39 | # # vector table 40 | # .data 41 | # .globl vectors 42 | # vectors: 43 | # .long vector0 44 | # .long vector1 45 | # .long vector2 46 | # ... 47 | 48 | -------------------------------------------------------------------------------- /xv6/vesamode.c: -------------------------------------------------------------------------------- 1 | /* 2 | * FileName: vesamode.c 3 | * Author: Liu Tongtong 4 | * Date: 2015.01.23 5 | * Version: 1.0 6 | * 7 | * TODO: 8 | * 1. The GUI may not work properly if the width and height changes. 9 | * You have to change the code according to SCREEN_WIDTH and SCREEN_HEIGHT. 10 | * 11 | */ 12 | 13 | #include "types.h" 14 | #include "defs.h" 15 | #include "memlayout.h" 16 | #include "vesamode.h" 17 | 18 | // Get the VESA mode information 19 | void vesamodeinit() 20 | { 21 | unsigned int memaddr = KERNBASE + 0x1028; 22 | unsigned int physaddr = *((unsigned int*)memaddr); 23 | SCREEN_PHYSADDR = (unsigned short*)physaddr; 24 | SCREEN_WIDTH = *((unsigned short*)(KERNBASE + 0x1012)); 25 | SCREEN_HEIGHT = *((unsigned short*)(KERNBASE + 0x1014)); 26 | VESA_ADDR = SCREEN_PHYSADDR; 27 | 28 | cprintf("SCREEN PHYSICAL ADDRESS: %x\n", SCREEN_PHYSADDR); 29 | cprintf("SCREEN WIDTH: %d\n", SCREEN_WIDTH); 30 | cprintf("SCREEN HEIGHT: %d\n", SCREEN_HEIGHT); 31 | cprintf("SCREEN BPP: %d\n", *((uchar*)(KERNBASE + 0x1019))); 32 | } 33 | -------------------------------------------------------------------------------- /xv6/vesamode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FileName: vesamode.h 3 | * Author: Liu Tongtong 4 | * Date: 2015.01.23 5 | * Version: 1.0 6 | * 7 | * TODO: 8 | * 1. The GUI may not work properly if the width and height changes. 9 | * You have to change the code according to SCREEN_WIDTH and SCREEN_HEIGHT. 10 | * 11 | */ 12 | 13 | // Global VESA mode information variables 14 | unsigned short SCREEN_WIDTH; 15 | unsigned short SCREEN_HEIGHT; 16 | unsigned short* SCREEN_PHYSADDR; 17 | unsigned short* VESA_ADDR; 18 | 19 | // Get the VESA mode information 20 | void vesamodeinit(); 21 | -------------------------------------------------------------------------------- /xv6/viewingmode1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/viewingmode1.bmp -------------------------------------------------------------------------------- /xv6/viewingmode2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THSS13/XV6/10aa797099e53cefc63b98ce2d3cf4feb57744f0/xv6/viewingmode2.bmp -------------------------------------------------------------------------------- /xv6/wc.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | char buf[512]; 6 | 7 | void 8 | wc(int fd, char *name) 9 | { 10 | int i, n; 11 | int l, w, c, inword; 12 | 13 | l = w = c = 0; 14 | inword = 0; 15 | while((n = read(fd, buf, sizeof(buf))) > 0){ 16 | for(i=0; i y ? x : y) 15 | typedef unsigned short color16; 16 | 17 | typedef struct Rect 18 | { 19 | int left_x; 20 | int left_y; 21 | int right_x; 22 | int right_y; 23 | //int rect_index; 24 | }Rect; 25 | 26 | typedef struct Window 27 | { 28 | int window_id; 29 | int pid; 30 | // int activated;//是否激活,1表示激活,0表示未激活,某一时刻只能有一个窗口被激活 31 | // char *window_title;//窗口标题栏字符串 32 | Rect window_position; 33 | //int z_order; 34 | struct Window *prior_window; 35 | struct Window *next_window; 36 | }Window; 37 | 38 | typedef Window* WindowLink;//用队列中的先后顺序表示窗口堆叠的次序 39 | 40 | extern WindowLink window_list; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /xv6/windowStyle.h: -------------------------------------------------------------------------------- 1 | #ifndef WINDOWSTYLE_H 2 | #define WINDOWSTYLE_H 3 | #define BORDERLINE_COLOR 0 4 | #define TOPBAR_COLOR 0x5ACB 5 | #define TOPBAR_HEIGHT 20 6 | #define BOTTOMBAR_COLOR 0x5ACB 7 | #define BOTTOMBAR_HEIGHT 20 8 | #define TITLE_OFFSET_X 25 9 | #define TITLE_OFFSET_Y 2 10 | #define TITLE_COLOR 0xFFFF 11 | #endif 12 | -------------------------------------------------------------------------------- /xv6/x86.h: -------------------------------------------------------------------------------- 1 | // Routines to let C code use special x86 instructions. 2 | 3 | static inline uchar 4 | inb(ushort port) 5 | { 6 | uchar data; 7 | 8 | asm volatile("in %1,%0" : "=a" (data) : "d" (port)); 9 | return data; 10 | } 11 | 12 | static inline ushort 13 | inw(ushort port) 14 | { 15 | ushort data; 16 | 17 | asm volatile("inw %w1,%0" : "=a" (data) : "d" (port)); 18 | return data; 19 | } 20 | 21 | static inline void 22 | insl(int port, void *addr, int cnt) 23 | { 24 | asm volatile("cld; rep insl" : 25 | "=D" (addr), "=c" (cnt) : 26 | "d" (port), "0" (addr), "1" (cnt) : 27 | "memory", "cc"); 28 | } 29 | 30 | static inline void 31 | outb(ushort port, uchar data) 32 | { 33 | asm volatile("out %0,%1" : : "a" (data), "d" (port)); 34 | } 35 | 36 | static inline void 37 | outw(ushort port, ushort data) 38 | { 39 | asm volatile("out %0,%1" : : "a" (data), "d" (port)); 40 | } 41 | 42 | static inline void 43 | outsl(int port, const void *addr, int cnt) 44 | { 45 | asm volatile("cld; rep outsl" : 46 | "=S" (addr), "=c" (cnt) : 47 | "d" (port), "0" (addr), "1" (cnt) : 48 | "cc"); 49 | } 50 | 51 | static inline void 52 | stosb(void *addr, int data, int cnt) 53 | { 54 | asm volatile("cld; rep stosb" : 55 | "=D" (addr), "=c" (cnt) : 56 | "0" (addr), "1" (cnt), "a" (data) : 57 | "memory", "cc"); 58 | } 59 | 60 | static inline void 61 | stosl(void *addr, int data, int cnt) 62 | { 63 | asm volatile("cld; rep stosl" : 64 | "=D" (addr), "=c" (cnt) : 65 | "0" (addr), "1" (cnt), "a" (data) : 66 | "memory", "cc"); 67 | } 68 | 69 | struct segdesc; 70 | 71 | static inline void 72 | lgdt(struct segdesc *p, int size) 73 | { 74 | volatile ushort pd[3]; 75 | 76 | pd[0] = size-1; 77 | pd[1] = (uint)p; 78 | pd[2] = (uint)p >> 16; 79 | 80 | asm volatile("lgdt (%0)" : : "r" (pd)); 81 | } 82 | 83 | struct gatedesc; 84 | 85 | static inline void 86 | lidt(struct gatedesc *p, int size) 87 | { 88 | volatile ushort pd[3]; 89 | 90 | pd[0] = size-1; 91 | pd[1] = (uint)p; 92 | pd[2] = (uint)p >> 16; 93 | 94 | asm volatile("lidt (%0)" : : "r" (pd)); 95 | } 96 | 97 | static inline void 98 | ltr(ushort sel) 99 | { 100 | asm volatile("ltr %0" : : "r" (sel)); 101 | } 102 | 103 | static inline uint 104 | readeflags(void) 105 | { 106 | uint eflags; 107 | asm volatile("pushfl; popl %0" : "=r" (eflags)); 108 | return eflags; 109 | } 110 | 111 | static inline void 112 | loadgs(ushort v) 113 | { 114 | asm volatile("movw %0, %%gs" : : "r" (v)); 115 | } 116 | 117 | static inline void 118 | cli(void) 119 | { 120 | asm volatile("cli"); 121 | } 122 | 123 | static inline void 124 | sti(void) 125 | { 126 | asm volatile("sti"); 127 | } 128 | 129 | static inline uint 130 | xchg(volatile uint *addr, uint newval) 131 | { 132 | uint result; 133 | 134 | // The + in "+m" denotes a read-modify-write operand. 135 | asm volatile("lock; xchgl %0, %1" : 136 | "+m" (*addr), "=a" (result) : 137 | "1" (newval) : 138 | "cc"); 139 | return result; 140 | } 141 | 142 | static inline uint 143 | rcr2(void) 144 | { 145 | uint val; 146 | asm volatile("movl %%cr2,%0" : "=r" (val)); 147 | return val; 148 | } 149 | 150 | static inline void 151 | lcr3(uint val) 152 | { 153 | asm volatile("movl %0,%%cr3" : : "r" (val)); 154 | } 155 | 156 | //PAGEBREAK: 36 157 | // Layout of the trap frame built on the stack by the 158 | // hardware and by trapasm.S, and passed to trap(). 159 | struct trapframe { 160 | // registers as pushed by pusha 161 | uint edi; 162 | uint esi; 163 | uint ebp; 164 | uint oesp; // useless & ignored 165 | uint ebx; 166 | uint edx; 167 | uint ecx; 168 | uint eax; 169 | 170 | // rest of trap frame 171 | ushort gs; 172 | ushort padding1; 173 | ushort fs; 174 | ushort padding2; 175 | ushort es; 176 | ushort padding3; 177 | ushort ds; 178 | ushort padding4; 179 | uint trapno; 180 | 181 | // below here defined by x86 hardware 182 | uint err; 183 | uint eip; 184 | ushort cs; 185 | ushort padding5; 186 | uint eflags; 187 | 188 | // below here only when crossing rings, such as from user to kernel 189 | uint esp; 190 | ushort ss; 191 | ushort padding6; 192 | }; 193 | -------------------------------------------------------------------------------- /xv6/zombie.c: -------------------------------------------------------------------------------- 1 | // Create a zombie process that 2 | // must be reparented at exit. 3 | 4 | #include "types.h" 5 | #include "stat.h" 6 | #include "user.h" 7 | 8 | int 9 | main(void) 10 | { 11 | if(fork() > 0) 12 | sleep(5); // Let child exit before parent. 13 | exit(); 14 | } 15 | --------------------------------------------------------------------------------