Full Code of hurley25/Hurlex-II for AI

master 9318f3401a37 cached
83 files
242.1 KB
69.2k tokens
433 symbols
1 requests
Download .txt
Showing preview only (279K chars total). Download the full file or copy to clipboard to get everything.
Repository: hurley25/Hurlex-II
Branch: master
Commit: 9318f3401a37
Files: 83
Total size: 242.1 KB

Directory structure:
gitextract_hd27az2o/

├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── arch/
│   ├── i386/
│   │   ├── debug/
│   │   │   └── debug.c
│   │   ├── driver/
│   │   │   ├── clock.c
│   │   │   ├── clock.h
│   │   │   ├── console.c
│   │   │   ├── console.h
│   │   │   ├── pic.c
│   │   │   └── pic.h
│   │   ├── include/
│   │   │   ├── arch.h
│   │   │   ├── atomic.h
│   │   │   ├── common.h
│   │   │   └── spinlock.h
│   │   ├── init/
│   │   │   ├── arch_init.c
│   │   │   ├── init.c
│   │   │   └── init_s.s
│   │   ├── intr/
│   │   │   ├── intr.c
│   │   │   ├── intr.h
│   │   │   └── intr_s.s
│   │   ├── mm/
│   │   │   ├── fault.c
│   │   │   ├── gdt.c
│   │   │   ├── gdt.h
│   │   │   ├── gdt_s.s
│   │   │   ├── pmm.c
│   │   │   ├── pmm.h
│   │   │   ├── vmm.c
│   │   │   └── vmm.h
│   │   ├── syscall/
│   │   │   ├── syscall.c
│   │   │   └── syscall.h
│   │   └── task/
│   │       ├── entry.s
│   │       ├── switch_to.s
│   │       ├── task.c
│   │       └── task.h
│   └── x64/
│       └── TODO
├── driver/
│   ├── block_dev.c
│   ├── char_dev.c
│   ├── device.c
│   ├── ide.c
│   └── kboard.c
├── fs/
│   ├── fs.c
│   ├── mbr.c
│   ├── ramfs/
│   │   └── ramfs.c
│   ├── sfs/
│   │   ├── sfs.c
│   │   └── sfs.h
│   └── vfs.c
├── include/
│   ├── block_dev.h
│   ├── char_dev.h
│   ├── debug.h
│   ├── device.h
│   ├── elf.h
│   ├── errno.h
│   ├── fs.h
│   ├── init.h
│   ├── kio.h
│   ├── lib/
│   │   ├── list.h
│   │   ├── rbtree.h
│   │   └── string.h
│   ├── mboot.h
│   ├── mbr.h
│   ├── mm/
│   │   ├── buddy_mm.h
│   │   ├── ff_mm.h
│   │   ├── mm.h
│   │   └── slob.h
│   ├── sched.h
│   ├── sync.h
│   ├── types.h
│   └── vargs.h
├── init/
│   └── kmain.c
├── isodir/
│   └── boot/
│       └── grub/
│           └── grub.cfg
├── kernel/
│   ├── errno.c
│   ├── kio.c
│   ├── printk.c
│   └── sched/
│       └── sched.c
├── lib/
│   ├── rbtree.c
│   └── string.c
├── mm/
│   ├── buddy_mm.c
│   ├── ff_mm.c
│   ├── mm.c
│   └── slob.c
└── scripts/
    ├── gdbinit
    └── kernel.ld

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Object files
*.o
*.ko
*.obj
*.elf
.clang_complete

# Precompiled Headers
*.gch
*.pch

# Libraries
*.lib
*.a
*.la
*.lo

# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib

# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex

# The Program files
*.img
hx_kernel
tags
*.iso


================================================
FILE: LICENSE
================================================
GNU GENERAL PUBLIC LICENSE
                       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

                    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

                            NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    {description}
    Copyright (C) {year}  {fullname}

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) year name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  {signature of Ty Coon}, 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.



================================================
FILE: Makefile
================================================
#!Makefile

# --------------------------------------------------------
#
#    hurlex 这个小内核的 Makefile
#
#    默认使用的C语言编译器是 GCC、汇编语言编译器是 nasm
#
#        qianyi.lh    2014/11/04   12:08:13
# --------------------------------------------------------

C_SOURCES = $(shell find . -name "*.c")
C_OBJECTS = $(patsubst %.c, %.o, $(C_SOURCES))
S_SOURCES = $(shell find . -name "*.s")
S_OBJECTS = $(patsubst %.s, %.o, $(S_SOURCES))

CC = gcc
LD = ld
ASM = nasm

C_FLAGS = -std=c99 -c -m32 -Wall -Wextra -ggdb -gstabs+ -ffreestanding \
                 -I. -Iinclude -Iarch/i386 -Iarch/i386/include -fno-stack-protector
LD_FLAGS = -T scripts/kernel.ld -nostdlib -m elf_i386
ASM_FLAGS = -f elf -g -F stabs

all: $(S_OBJECTS) $(C_OBJECTS) link update_fd

# The automatic variable `$<' is just the first prerequisite
.c.o:
	@echo 编译代码文件 $< ...
	$(CC) $(C_FLAGS) $< -o $@

.s.o:
	@echo 编译汇编文件 $< ...
	$(ASM) $(ASM_FLAGS) $<

link:
	@echo 链接内核文件...
	$(LD) $(LD_FLAGS) $(S_OBJECTS) $(C_OBJECTS) -o hx_kernel

.PHONY:clean
clean:
	$(RM) $(S_OBJECTS) $(C_OBJECTS) hx_kernel

.PHONY:update_fd
update_fd:
	sudo mount floppy.img /mnt/kernel
	sudo cp hx_kernel /mnt/kernel/hx_kernel
	sleep 1
	sudo umount /mnt/kernel

.PHONY:mount_image
mount_image:
	sudo mount floppy.img /mnt/kernel

.PHONY:umount_image
umount_image:
	sudo umount /mnt/kernel

.PHONY:iso
iso:
	cp hx_kernel isodir/boot/
	grub2-mkrescue -o hurlex.iso isodir

.PHONY:runiso
runiso:
	qemu -m 128 -hda disk.img -cdrom hurlex.iso -boot d

.PHONY:runfd
runfd:
	qemu -m 128 -hda disk.img -fda floppy.img -boot a

.PHONY:qemu
qemu:
	qemu -m 128 -hda disk.img -kernel hx_kernel

.PHONY:debug
debug:
	qemu -S -s -m 128 -hda disk.img -fda floppy.img -boot a &
	sleep 1
	cgdb -x scripts/gdbinit

.PHONY:code_line_count
code_line_count:
	find . -type f -name "*.[c|h|s]" -exec cat {} \; | wc -l


================================================
FILE: README.md
================================================
Hurlex II
======

一个运行在x86-IA32架构下的小内核,仅作为操作系统理论学习的参考。

第二版重新设计和构思,参考一些优秀的实现进行补充设计和编码。


================================================
FILE: arch/i386/debug/debug.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  debug.c
 *
 *    Description:  调试相关的函数
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 10时54分39秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <common.h>
#include <debug.h>
#include <elf.h>
#include <lib/string.h>
#include <mm/mm.h>

static elf_t kernel_elf;

static void elf_from_multiboot(multiboot_t *mb);

static void print_stack_trace();

static const char *elf_lookup_symbol(uint32_t addr, elf_t *elf);

void debug_init(void)
{
        // 从 GRUB 提供的信息中获取到内核符号表和代码地址信息
        elf_from_multiboot(glb_mboot_ptr);
}

static void elf_from_multiboot(multiboot_t *mb)
{
        elf_section_header_t *sh = (elf_section_header_t *)(mb->addr);

        uint32_t shstrtab = sh[mb->shndx].addr;
        for (uint32_t i = 0; i < mb->num; i++) {
                const char *name = (const char *)(shstrtab + sh[i].name) + PAGE_OFFSET;
                // 在 GRUB 提供的 multiboot 信息中寻找内核 ELF 格式所提取的字符串表和符号表
                if (strcmp(name, ".strtab") == 0) {
                        kernel_elf.strtab = (const char *)sh[i].addr + PAGE_OFFSET;
                        kernel_elf.strtabsz = sh[i].size;
                }
                if (strcmp(name, ".symtab") == 0) {
                        kernel_elf.symtab = (elf_symbol_t *)(sh[i].addr + PAGE_OFFSET);
                        kernel_elf.symtabsz = sh[i].size;
                }
        }
}

void panic(const char *msg)
{
        printk("*** System panic: %s\n", msg);
        print_stack_trace();
        printk("***\n");
        
        // 致命错误发生后打印栈信息后停止在这里
        while(1) {
        	cpu_hlt();
        }
}

void print_stack_trace(void)
{
        uint32_t *ebp, *eip;

        __asm__ volatile ("mov %%ebp, %0" : "=r" (ebp));
        while (ebp) {
                eip = ebp + 1;
                printk("   [0x%x] %s\n", *eip, elf_lookup_symbol(*eip, &kernel_elf));
                ebp = (uint32_t*)*ebp;
        }
}

static const char *elf_lookup_symbol(uint32_t addr, elf_t *elf)
{
        for (uint32_t i = 0; i < (elf->symtabsz / sizeof(elf_symbol_t)); i++) {
                if (ELF32_ST_TYPE(elf->symtab[i].info) != 0x2) {
                      continue;
                }
                // 通过函数调用地址查到函数的名字(地址在该函数的代码段地址区间之内)
                if ( (addr >= elf->symtab[i].value) && (addr < (elf->symtab[i].value + elf->symtab[i].size)) ) {
                        return (const char *)((uint32_t)elf->strtab + elf->symtab[i].name);
                }
        }

        return NULL;
}

void print_cur_status(void)
{
        static int round = 0;
        uint16_t reg1, reg2, reg3, reg4;

        __asm__ volatile ( "mov %%cs, %0;"
                           "mov %%ds, %1;"
                           "mov %%es, %2;"
                           "mov %%ss, %3;"
                           : "=m"(reg1), "=m"(reg2), "=m"(reg3), "=m"(reg4));

        // 打印当前的运行级别
        printk("%d: @ring %d\n", round, reg1 & 0x3);
        printk("%d:  cs = %x\n", round, reg1);
        printk("%d:  ds = %x\n", round, reg2);
        printk("%d:  es = %x\n", round, reg3);
        printk("%d:  ss = %x\n", round, reg4);
        ++round;
}

void show_memory_map(void)
{
        uint32_t mmap_addr = glb_mboot_ptr->mmap_addr;
        uint32_t mmap_length = glb_mboot_ptr->mmap_length;

        printk("Memory map:\n\n");

        mmap_entry_t *mmap = (mmap_entry_t *)mmap_addr;
        for (mmap = (mmap_entry_t *)mmap_addr; (uint32_t)mmap < mmap_addr + mmap_length; mmap++) {
                printk("base_addr = 0x%X%08X, length = 0x%X%08X, type = 0x%X\n",
                        (uint32_t)mmap->base_addr_high, (uint32_t)mmap->base_addr_low,
                        (uint32_t)mmap->length_high, (uint32_t)mmap->length_low,
                        (uint32_t)mmap->type);
        }
        printk("\n");
}

void show_kernel_memory_map(void)
{
        printk("kernel in memory start: 0x%08X\n", kern_start);
	printk("kernel in memory end:   0x%08X\n", kern_end);
        
	printk("\nkernel segment in memory:\n");
	printk("  .init.text    0x%08X ~ 0x%08X \n", kern_init_text_start, kern_init_text_end);
	printk("  .init.data    0x%08X ~ 0x%08X \n", kern_init_data_start, kern_init_data_end);
	printk("  .text         0x%08X ~ 0x%08X \n", kern_text_start, kern_text_end);
	printk("  .data         0x%08X ~ 0x%08X \n", kern_data_start, kern_data_end);
        
	printk("\nkernel in memory used: %d KB = %d Pages\n\n",
                        (kern_end - kern_start) / 1024, (kern_end - kern_start) / 1024 / 4);
}



================================================
FILE: arch/i386/driver/clock.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  clock.c
 *
 *    Description:  定时中断函数
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 14时58分12秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <debug.h>
#include <common.h>
#include <arch.h>
#include <sched.h>

#include "clock.h"

#define FREQUENCY       100

// 定时中断由 8253/8254 芯片从 IRQ0 提供
#define IO_TIMER        0x040               // 8253 Timer #1

// 输入频率为 1193180,frequency 即每秒中断次数
#define TIMER_FREQ      1193180

// Intel 8253/8254 PIT芯片 I/O端口地址范围是40h~43h
#define TIMER_MODE      (IO_TIMER + 3)         // timer mode port

#define TIMER_SEL0      0x00                    // select counter 0
#define TIMER_RATEGEN   0x04                    // mode 2
#define TIMER_CLK       0x06                    // mode 3
#define TIMER_16BIT     0x30                    // r/w counter 16 bits, LSB first

void clock_init(void)
{
        // 注册时间相关的处理函数
        register_interrupt_handler(IRQ0, clock_callback);

        uint32_t divisor = TIMER_FREQ / FREQUENCY;

        outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);

        // 拆分低字节和高字节
        uint8_t low = (uint8_t)(divisor & 0xFF);
        uint8_t hign = (uint8_t)((divisor >> 8) & 0xFF);
        
        // 分别写入低字节和高字节
        outb(IO_TIMER, low);
        outb(IO_TIMER, hign);
}



================================================
FILE: arch/i386/driver/clock.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  clock.h
 *
 *    Description:  定时中断相关
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 15时01分16秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_TIMER_H_
#define INCLUDE_TIMER_H_

#include <types.h>

void clock_init(void);

#endif  // INCLUDE_TIMER_H_


================================================
FILE: arch/i386/driver/console.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  console.c
 *
 *    Description:  80 * 25 显示模式驱动程序
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 10时44分26秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <common.h>
#include <debug.h>
#include <sync.h>
#include <mm/mm.h>

#include "console.h"

/*
 * VGA(Video Graphics Array,视频图形阵列)是使用模拟信号的一种视频传输标准,
 * 内核可以通过它来控制屏幕上字符或者图形的显示。
 * 在默认的文本模式(Text-Mode)下,VGA控制器保留了一块内存(0x8b000~0x8bfa0)
 * 作为屏幕上字符显示的缓冲区,若要改变屏幕上字符的显示,只需要修改这块内存就好了。
 */
 
// VGA 的显示缓冲的起点是 0xB8000
static uint16_t *video_memory = (uint16_t *)(0xB8000 + PAGE_OFFSET);

// 屏幕"光标"的坐标
static uint16_t cursor_x = 0;
static uint16_t cursor_y = 0;

// 屏幕是 80 * 25
#define CON_WIDTH  80
#define CON_HIGH   25

// VGA内存输入缓冲区 80 * 128
#define BUFF_WIDTH  80
#define BUFF_HIGH   128

// VGA 输出缓冲区
static uint16_t video_buffer[BUFF_WIDTH * BUFF_HIGH];

// buffer 输出的坐标
static uint16_t buffer_x = 0;
static uint16_t buffer_y = 0;

// 当前屏幕显示在缓冲区的起始位置
static uint16_t current_line = 0;

// VGA 内部的寄存器多达300多个,显然无法一一映射到I/O端口的地址空间。
// 对此 VGA 控制器的解决方案是,将一个端口作为内部寄存器的索引:0x3D4,
// 再通过 0x3D5 端口来设置相应寄存器的值。
#define VGA_IDX   0x3D4
#define VGA_SET   0x3D5

// 在这里用到的两个内部寄存器的编号为0xE与0xF,分别表示光标位置的高8位与低8位。
#define CUR_HIGH  0xE
#define CUR_LOW   0xF

// 移动光标
static void move_cursor(void);

// 刷新屏幕显示到当前输出位置
static void _flush_console_current(void);

// 屏幕显示初始化
void console_init(void)
{
        console_clear();
        cprintk(rc_black, rc_green, "Hello, Hurlex II kernel!\n\n");
}

// 清屏操作
void console_clear(void)
{
        uint8_t attribute_byte = (0 << 4) | (15 & 0x0F);
        uint16_t blank = 0x20 | (attribute_byte << 8);

        // 初始化 console 数据
        for (uint32_t i = 0; i < CON_WIDTH * CON_HIGH; ++i) {
              video_memory[i] = blank;
        }
        cursor_x = 0;
        cursor_y = 0;
        move_cursor();

        // 初始化 buffer 数据
        for (uint32_t i = 0; i < BUFF_WIDTH * BUFF_HIGH; ++i) {
              video_buffer[i] = blank;
        }
        
        buffer_x = 0;
        buffer_y = 0;
        
        current_line = 0;
}

// 移动光标
static void move_cursor(void)
{
        uint16_t cursor = cursor_y * CON_WIDTH + cursor_x;
        
        outb(VGA_IDX, CUR_HIGH);                  // 告诉 VGA 我们要设置光标的高字节
        outb(VGA_SET, (cursor >> 8) & 0xFF);      // 发送高 8 位
        outb(VGA_IDX, CUR_LOW);                   // 告诉 VGA 我们要设置光标的低字节
        outb(VGA_SET, cursor & 0xFF);             // 发送低 8 位
}

// 滚动缓冲区
static void scroll_buffer(void)
{
        // attribute_byte 被构造出一个黑底白字的描述格式
        uint8_t attribute_byte = (0 << 4) | (15 & 0x0F);
        uint16_t blank = 0x20 | (attribute_byte << 8);  // space 是 0x20

        // buffer_y 到 BUFF_HIGH - 1 的时候,就该换行了
        if (buffer_y == BUFF_HIGH - 1) {

                // 将所有行的显示数据复制到上一行,第一行永远消失了...
                for (uint32_t i = 0 * BUFF_WIDTH; i < (BUFF_HIGH-1) * BUFF_WIDTH; i++) {
                      video_buffer[i] = video_buffer[i+BUFF_WIDTH];
                }

                // 最后的一行数据现在填充空格,不显示任何字符
                for (uint32_t i = (BUFF_HIGH-1) * BUFF_WIDTH; i < BUFF_HIGH * BUFF_WIDTH; i++) {
                      video_buffer[i] = blank;
                }

                buffer_y--;
        }
}

// 屏幕输出一个字符(带颜色)
static void console_putc_color(char c, real_color_t back, real_color_t fore)
{
        uint8_t back_color = (uint8_t)back;
        uint8_t fore_color = (uint8_t)fore;

        uint8_t attribute_byte = (back_color << 4) | (fore_color & 0x0F);
        uint16_t attribute = attribute_byte << 8;

        // 0x08 是 退格键 的 ASCII 码
        // 0x09 是 tab 键 的 ASCII 码
        if (c == 0x08 && buffer_x) {
              buffer_x--;
        } else if (c == 0x09) {
              buffer_x = (buffer_x+8) & ~(8-1);
        } else if (c == '\r') {
              buffer_x = 0;
        } else if (c == '\n') {
                buffer_x = 0;
                buffer_y++;
        } else if (c >= ' ') {
                video_buffer[buffer_y * BUFF_WIDTH + buffer_x] = c | attribute;
                buffer_x++;
        }

        // 每 80 个字符一行,满80就必须换行了
        if (buffer_x == BUFF_WIDTH) {
                buffer_x = 0;
                buffer_y ++;
        }

        // 滚动缓冲区
        scroll_buffer();
}

// 屏幕打印一个以 \0 结尾的字符串(默认黑底白字)
void console_write(char *cstr)
{
        bool intr_flag = false;
        local_intr_store(intr_flag);
        {
                while (*cstr) {
                        console_putc_color(*cstr++, rc_black, rc_white);
                }
                _flush_console_current();
        }
        local_intr_restore(intr_flag);
}

// 屏幕打印一个以 \0 结尾的字符串(带颜色)
void console_write_color(char *cstr, real_color_t back, real_color_t fore)
{
        bool intr_flag = false;
        local_intr_store(intr_flag);
        {
                while (*cstr) {
                        console_putc_color(*cstr++, back, fore);
                }
                _flush_console_current();
        }
        local_intr_restore(intr_flag);
}

// 刷新屏幕显示到指定位置
static void _flush_console(void)
{
        uint8_t attribute_byte = (0 << 4) | (15 & 0x0F);
        uint16_t blank = 0x20 | (attribute_byte << 8);
        uint16_t begin_line = 0, end_line = 0;

        begin_line = current_line;        
        end_line = buffer_y + 1;

        uint32_t i = 0;
        for (uint32_t j = begin_line * CON_WIDTH; j < end_line * CON_WIDTH; ++j) {
                video_memory[i] = video_buffer[j];
                i++;
        }

        while (i < CON_WIDTH * CON_HIGH) {
                video_memory[i] = blank;
                i++;
        }

        cursor_x = buffer_x;
        cursor_y = end_line - begin_line - 1;

        move_cursor();
}

// 刷新屏幕显示到当前输出位置
static void _flush_console_current(void)
{
        if (buffer_y >= CON_HIGH - 1) {
                current_line = buffer_y - CON_HIGH + 1; 
        } else {
                current_line = 0;
        }
        _flush_console();
}

// 屏幕显示向上移动n行
void console_view_up(uint16_t offset)
{
        if (current_line >= offset) {
                current_line -= offset;
        } else {
                current_line = 0;
        }
        _flush_console();
}

// 屏幕显示向下移动n行
void console_view_down(uint16_t offset)
{
        if (current_line + offset < buffer_y) {
                current_line += offset;
        } else {
                current_line = buffer_y;
        }
        _flush_console();
}



================================================
FILE: arch/i386/driver/console.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  console.h
 *
 *    Description:  屏幕输出函数
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 10时49分13秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_CONSOLE_H_
#define INCLUDE_CONSOLE_H_

#include <types.h>

typedef
enum real_color {
        rc_black = 0,
        rc_blue = 1,
        rc_green = 2,
        rc_cyan = 3,
        rc_red = 4,
        rc_magenta = 5,
        rc_brown = 6,
        rc_light_grey = 7,
        rc_dark_grey = 8,
        rc_light_blue = 9,
        rc_light_green = 10,
        rc_light_cyan = 11,
        rc_light_red = 12,
        rc_light_magenta = 13,
        rc_light_brown  = 14,
        rc_white = 15
} real_color_t;

// 屏幕显示初始化
void console_init(void);

// 清屏操作
void console_clear(void);

// 屏幕打印一个以 \0 结尾的字符串(默认黑底白字)
void console_write(char *cstr);

// 屏幕打印一个以 \0 结尾的字符串(带颜色)
void console_write_color(char *cstr, real_color_t back, real_color_t fore);

// 屏幕显示向上移动n行
void console_view_up(uint16_t offset);

// 屏幕显示向下移动n行
void console_view_down(uint16_t offset);

#endif  // INCLUDE_CONSOLE_H_


================================================
FILE: arch/i386/driver/pic.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  pic.c
 *
 *    Description:  PIC 相关
 *
 *        Version:  1.0
 *        Created:  2014年11月06日 09时48分25秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <common.h>

#include "pic.h"

#define IO_PIC1   (0x20)	  // Master (IRQs 0-7)
#define IO_PIC2   (0xA0)	  // Slave  (IRQs 8-15)

#define IO_PIC1C  (IO_PIC1+1)
#define IO_PIC2C  (IO_PIC2+1)

// 设置 8259A 芯片
void init_interrupt_chip(void)
{
        // 重新映射 IRQ 表
        // 两片级联的 Intel 8259A 芯片
        // 主片端口 0x20 0x21
        // 从片端口 0xA0 0xA1
        
        // 初始化主片、从片
        // 0001 0001
        outb(IO_PIC1, 0x11);
        outb(IO_PIC2, 0x11);

        // 设置主片 IRQ 从 0x20(32) 号中断开始
        outb(IO_PIC1C, 0x20);

        // 设置从片 IRQ 从 0x28(40) 号中断开始
        outb(IO_PIC2C, 0x28);
        
        // 设置主片 IR2 引脚连接从片
        outb(IO_PIC1C, 0x04);

        // 告诉从片输出引脚和主片 IR2 号相连
        outb(IO_PIC2C, 0x02);
        
        // 设置主片和从片按照 8086 的方式工作
        outb(IO_PIC1C, 0x01);
        outb(IO_PIC2C, 0x01);
        
        // 设置主从片允许中断
        outb(IO_PIC1C, 0x0);
        outb(IO_PIC2C, 0x0);
}

// 重设 8259A 芯片
void clear_interrupt_chip(uint32_t intr_no)
{
        // 发送中断结束信号给 PICs
        // 按照我们的设置,从 32 号中断起为用户自定义中断
        // 因为单片的 Intel 8259A 芯片只能处理 8 级中断
        // 故大于等于 40 的中断号是由从片处理的
        if (intr_no >= 40) {
                // 发送重设信号给从片
                outb(IO_PIC2, 0x20);
        }
        // 发送重设信号给主片
        outb(IO_PIC1, 0x20);
}



================================================
FILE: arch/i386/driver/pic.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  pic.h
 *
 *    Description:  PIC 相关
 *
 *        Version:  1.0
 *        Created:  2014年11月06日 09时51分59秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_PIC_H_
#define INCLUDE_PIC_H_

#include <arch.h>

// 设置8259A芯片
void init_interrupt_chip(void);

// 重设 8259A 芯片
void clear_interrupt_chip(uint32_t intr_no);

#endif  // INCLUDE_PIC_H_


================================================
FILE: arch/i386/include/arch.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  arch.h
 *
 *    Description:  架构相关的头文件引用
 *
 *        Version:  1.0
 *        Created:  2014年11月05日 09时48分34秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef ARCH_H_
#define ARCH_H_

#include <mm/gdt.h>
#include <intr/intr.h>
#include <driver/pic.h>
#include <driver/clock.h>
#include <driver/console.h>
#include <task/task.h>

// 架构相关的初始化
void arch_init(void);

#endif  // ARCH_H_


================================================
FILE: arch/i386/include/atomic.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  atomic.h
 *
 *    Description:  一些原子操作
 *
 *        Version:  1.0
 *        Created:  2014年11月08日 20时51分18秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef ATOMIC_H_
#define ATOMIC_H_

#include <types.h>

#define LOCK_PREFIX "lock;"

#define ATOMIC_INIT(i)  { (i) }

static inline void set_bit(int32_t nr, volatile void *addr)
{
        __asm__ volatile ("btsl %1, %0" 
                        :"=m" (*(volatile long *)addr) 
                        : "Ir" (nr));
}

static inline void clear_bit(int32_t nr, volatile void *addr)
{
        __asm__ volatile ("btrl %1, %0" 
                        :"=m" (*(volatile long *)addr) 
                        : "Ir" (nr));
}

static inline void change_bit(int32_t nr, volatile void *addr)
{
        __asm__ volatile ("btcl %1, %0" 
                        :"=m" (*(volatile long *)addr) 
                        : "Ir" (nr));
}

static inline bool test_bit(int32_t nr, volatile void *addr)
{
        int32_t oldbit;
        
        __asm__ volatile ("btl %2, %1; sbbl %0,%0" 
                        : "=r" (oldbit) 
                        : "m" (*(volatile long *)addr), "Ir" (nr));
        
        return (oldbit != 0);
}

static inline int32_t atomic_read(const atomic_t *v)
{
        return v->counter;
}

static inline void atomic_set(atomic_t *v, int32_t i)
{
        v->counter = i;
}

static inline void atomic_add(atomic_t *v, int32_t i)
{
        __asm__ volatile(LOCK_PREFIX "addl %1,%0"
                     : "+m" (v->counter)
                     : "ir" (i));
}

static inline void atomic_sub(atomic_t *v, int32_t i)
{
        __asm__ volatile(LOCK_PREFIX "subl %1,%0"
                     : "+m" (v->counter)
                     : "ir" (i));
}

static inline int32_t atomic_sub_and_test(atomic_t *v, int32_t i)
{
        unsigned char c;

        __asm__ volatile(LOCK_PREFIX "subl %2,%0; sete %1"
                     : "+m" (v->counter), "=qm" (c)
                     : "ir" (i) : "memory");
        return c;
}

static inline void atomic_inc(atomic_t *v)
{
        __asm__ volatile(LOCK_PREFIX "incl %0"
                     : "+m" (v->counter));
}

static inline int32_t atomic_inc_and_test(atomic_t *v)
{
        unsigned char c;

        __asm__ volatile(LOCK_PREFIX "incl %0; sete %1"
                     : "+m" (v->counter), "=qm" (c)
                     : : "memory");
        return (c != 0);
}

static inline void atomic_dec(atomic_t *v)
{
        __asm__ volatile(LOCK_PREFIX "decl %0"
                     : "+m" (v->counter));
}

static inline int32_t atomic_dec_and_test(atomic_t *v)
{
        unsigned char c;

        __asm__ volatile(LOCK_PREFIX "decl %0; sete %1"
                     : "+m" (v->counter), "=qm" (c)
                     : : "memory");
        return (c != 0);
}

#endif  // ATOMIC_H_


================================================
FILE: arch/i386/include/common.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  common.h
 *
 *    Description:  杂项函数
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 10时48分17秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_COMMON_H_
#define INCLUDE_COMMON_H_

#include "types.h"

/* Eflags register */
#define FL_CF           0x00000001  // Carry Flag
#define FL_PF           0x00000004  // Parity Flag
#define FL_AF           0x00000010  // Auxiliary carry Flag
#define FL_ZF           0x00000040  // Zero Flag
#define FL_SF           0x00000080  // Sign Flag
#define FL_TF           0x00000100  // Trap Flag
#define FL_IF           0x00000200  // Interrupt Flag
#define FL_DF           0x00000400  // Direction Flag
#define FL_OF           0x00000800  // Overflow Flag
#define FL_IOPL_MASK    0x00003000  // I/O Privilege Level bitmask
#define FL_IOPL_0       0x00000000  // IOPL == 0
#define FL_IOPL_1       0x00001000  // IOPL == 1
#define FL_IOPL_2       0x00002000  // IOPL == 2
#define FL_IOPL_3       0x00003000  // IOPL == 3
#define FL_NT           0x00004000  // Nested Task
#define FL_RF           0x00010000  // Resume Flag
#define FL_VM           0x00020000  // Virtual 8086 mode
#define FL_AC           0x00040000  // Alignment Check
#define FL_VIF          0x00080000  // Virtual Interrupt Flag
#define FL_VIP          0x00100000  // Virtual Interrupt Pending
#define FL_ID           0x00200000  // ID flag

#define __barrier__() __asm__ volatile ("" ::: "memory")

// 端口写一个字节
static inline void outb(uint16_t port, uint8_t value)
{
        __asm__ volatile ("outb %1, %0" : : "dN" (port), "a" (value));
}

// 端口读一个字节
static inline uint8_t inb(uint16_t port)
{
        uint8_t ret;

        __asm__ volatile("inb %1, %0" : "=a" (ret) : "dN" (port));

        return ret;
}

// 端口读一个字
static inline uint16_t inw(uint16_t port)
{
        uint16_t ret;

        __asm__ volatile ("inw %1, %0" : "=a" (ret) : "dN" (port));

        return ret;
}

static inline void insl(uint32_t port, void *addr, int cnt)
{
        __asm__ volatile (
                        "cld;"
                        "repne; insl;"
                        : "=D" (addr), "=c" (cnt)
                        : "d" (port), "0" (addr), "1" (cnt)
                        : "memory", "cc");
}

static inline void outsl(uint32_t port, const void *addr, int cnt)
{
        __asm__ volatile (
                        "cld;"
                        "repne; outsl;"
                        : "=S" (addr), "=c" (cnt)
                        : "d" (port), "0" (addr), "1" (cnt)
                        : "memory", "cc");
}

// 开启中断
static inline void enable_intr(void)
{
        __asm__ volatile ("sti");
}

// 关闭中断
static inline void disable_intr(void)
{
        __asm__ volatile ("cli" ::: "memory");
}

// 执行CPU空操作
static inline void cpu_hlt(void)
{
        __asm__ volatile ("hlt");
}

// 读取 EFLAGS
static inline uint32_t read_eflags(void)
{
        uint32_t eflags;

        __asm__ volatile ("pushfl; popl %0" : "=r" (eflags));

        return eflags;
}

// 写入EFALGS
static inline void write_eflags(uint32_t eflags)
{
        __asm__ volatile ("pushl %0; popfl" :: "r" (eflags));
}

// 修改当前页表
static inline void switch_pgd(uint32_t pd)
{
        __asm__ volatile ("mov %0, %%cr3" : : "r" (pd));
}

// 通知 CPU 更新页表缓存
static inline void tlb_reload_page(uint32_t va)
{
        __asm__ volatile ("invlpg (%0)" : : "a" (va));
}

// 修改栈地址
static inline void load_esp(uint32_t esp)
{
        __asm__ volatile ("mov %0, %%esp" : : "r" (esp));
}

#endif  // INCLUDE_COMMON_H_


================================================
FILE: arch/i386/include/spinlock.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  spinlock.h
 *
 *    Description:  自旋锁的实现
 *
 *        Version:  1.0
 *        Created:  2014年11月12日 11时16分51秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */


#ifndef INCLUDE_SPINLOCK_H_
#define INCLUDE_SPINLOCK_H_

#include <types.h>

typedef
struct spinlock_t {
        volatile uint32_t lock;
} spinlock_t;

// 1 表示 spinlock 可用
#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 }

// 初始化自旋锁
#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)

// spinlock 加锁
static inline void spinlock_lock(spinlock_t *lock)
{
        __asm__ volatile ("\n1:\t"
                        "lock; decb %0\n\t"                     // decb 将 lock->lock 减 1,lock 表示要锁住地址总线
                        "js 2f\n\t" 
                        ".section .text.lock, \"ax\"\n"
                        "2:\t" 
                        "cmpb $0, %0\n\t" 
                        "rep; nop\n\t" 
                        "jle 2b\n\t" 
                        "jmp 1b\n\t" 
                        ".previous"
                        :"=m" (lock->lock) : : "memory"); 
}

// spinlock 解锁
static inline void spinlock_unlock(spinlock_t *lock)
{
        __asm__ volatile ("movb $1, %0" 
                        :"=m" (lock->lock) : : "memory");
}

#endif // INCLUDE_SPINLOCK_H_


================================================
FILE: arch/i386/init/arch_init.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  arch_init.c
 *
 *    Description:  体系结构相关初始化
 *
 *        Version:  1.0
 *        Created:  2015年02月03日 16时26分53秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <arch.h>

// 体系结构相关的初始化函数
void arch_init(void)
{
        gdt_init();
        idt_init();
        clock_init();
        console_init();
}



================================================
FILE: arch/i386/init/init.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  init.c
 *
 *    Description:  内核初始化
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 10时03分01秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <common.h>
#include <debug.h>
#include <init.h>
#include <mm/mm.h>

// 开启分页机制之后的 Multiboot 数据指针
multiboot_t *glb_mboot_ptr;

// 开启分页机制之后的内核栈
uint8_t kern_stack[STACK_SIZE]  __attribute__ ((aligned(STACK_SIZE)));

// 内核栈的栈顶
uint32_t kern_stack_top = (uint32_t)kern_stack + STACK_SIZE;

// 内核使用的临时页表和页目录
// 该地址必须是页对齐的地址,内存 0-640KB 肯定是空闲的
__attribute__((section(".init.data"))) pgd_t *pgd_tmp  = (pgd_t *)0x1000;
__attribute__((section(".init.data"))) pte_t *pte_low  = (pte_t *)0x2000;
__attribute__((section(".init.data"))) pte_t *pte_hign = (pte_t *)0x3000;

// 映射临时页表
__attribute__((section(".init.text"))) void mmap_tmp_page(void);

// 启用分页
__attribute__((section(".init.text"))) void enable_paging(void);

// 内核入口函数
__attribute__((section(".init.text"))) void kern_entry(void)
{
        // 映射临时页表
        mmap_tmp_page();

        // 启用分页
        enable_paging();

        // 切换临时内核栈到分页后的新栈
        __asm__ volatile ("mov %0, %%esp\n\t"
                        "xor %%ebp, %%ebp" : : "r" (kern_stack_top));

        // 更新全局 multiboot_t 指针指向
        glb_mboot_ptr = (multiboot_t *)((uint32_t)mboot_ptr_tmp + PAGE_OFFSET);

        // 调用内核初始化函数
        kern_init();

        // 之前的函数调用链自栈切换后断开,无法再返回之前的调用点
}

// 映射临时页表
__attribute__((section(".init.text"))) void mmap_tmp_page(void)
{
        pgd_tmp[0] = (uint32_t)pte_low | PAGE_PRESENT | PAGE_WRITE;

        for (int i = 0; i < 4; ++i) {
                uint32_t pgd_idx = PGD_INDEX(PAGE_OFFSET + PAGE_MAP_SIZE * i);
                pgd_tmp[pgd_idx] = ((uint32_t)pte_hign + PAGE_SIZE * i) | PAGE_PRESENT | PAGE_WRITE;
        }

        // 映射内核虚拟地址 4MB 到物理地址的前 4MB
        // 因为 .init.text 段的代码在物理地址前 4MB 处(肯定不会超出这个范围),
        // 开启分页后若此处不映射,代码执行立即会出错,离开 .init.text 段后的代码执行,
        // 不再需要映射物理前 4MB 的内存
        for (int i = 0; i < 1024; i++) {
                pte_low[i] = (i << 12) | PAGE_PRESENT | PAGE_WRITE;
        }

        // 映射 0x00000000-0x01000000 的物理地址到虚拟地址 0xC0000000-0xC1000000
        for (int i = 0; i < 1024 * 4; i++) {
                pte_hign[i] = (i << 12) | PAGE_PRESENT | PAGE_WRITE;
        }
        
        // 设置临时页表
        __asm__ volatile ("mov %0, %%cr3" : : "r" (pgd_tmp));
}

// 启用分页
__attribute__((section(".init.text"))) void enable_paging(void)
{
        uint32_t cr0;
        
        __asm__ volatile ("mov %%cr0, %0" : "=r" (cr0));
        // 最高位 PG 位置 1,分页开启
        cr0 |= (1u << 31);
        __asm__ volatile ("mov %0, %%cr0" : : "r" (cr0));
}



================================================
FILE: arch/i386/init/init_s.s
================================================
; ----------------------------------------------------------------
;
;       init.s -- 内核从这里开始
;
;       qianyi.lh   2014/11/04   9:30:50
; ----------------------------------------------------------------

; 一些宏定义
MBOOT_HEADER_MAGIC      equ     0x1BADB002      ; Multiboot 魔数,由规范决定的

MBOOT_PAGE_ALIGN        equ     1 << 0          ; 0 号位表示所有的引导模块将按页(4KB)边界对齐
MBOOT_MEM_INFO          equ     1 << 1          ; 1 号位通过 Multiboot 信息结构的 mem_* 域包括可用内存的信息

; 定义我们使用的 Multiboot 的标记
MBOOT_HEADER_FLAGS      equ     MBOOT_PAGE_ALIGN | MBOOT_MEM_INFO

; 域checksum是一个32位的无符号值,当与其他的magic域(也就是magic和flags)相加时,
; 要求其结果必须是32位的无符号值 0 (即magic + flags + checksum = 0)
MBOOT_CHECKSUM          equ     - (MBOOT_HEADER_MAGIC + MBOOT_HEADER_FLAGS)

; ----------------------------------------------------------------
;   符合Multiboot规范的 OS 映象需要这样一个 magic Multiboot 头
;       ----------------------------------
;         偏移量  类型  域名        备注
;
;           0     u32   magic       必需
;           4     u32   flags       必需 
;           8     u32   checksum    必需 
;       ----------------------------------
; ----------------------------------------------------------------

[BITS 32]               ; 所有代码以 32-bit 的方式编译

section .init.text      ; 临时代码段从这里开始

; 在代码段的起始位置定义符合 Multiboot 规范的标记

dd MBOOT_HEADER_MAGIC   ; GRUB 会通过这个魔数判断该映像是否支持
dd MBOOT_HEADER_FLAGS   ; GRUB 的一些加载时选项,其详细注释在定义处
dd MBOOT_CHECKSUM       ; 检测数值,其含义在定义处

[GLOBAL start]          ; 内核代码入口,此处提供该声明给 ld 链接器
[GLOBAL mboot_ptr_tmp]  ; 全局的 struct multiboot * 变量
[EXTERN kern_entry]     ; 声明内核 C 代码的入口函数

start:
        mov [mboot_ptr_tmp], ebx        ; 将 ebx 中的指针存入 mboot_ptr_tmp
        mov esp, STACK_TOP              ; 设置内核栈地址
        and esp, 0FFFFFFF0H             ; 栈地址按照 16 字节对齐
        mov ebp, 0                      ; 帧指针修改为 0
    
        call kern_entry                 ; 调用内核入口函数

noreturn:                               ; 代码永远不会返回到这里
        hlt
        jmp noreturn

;-----------------------------------------------------------------------------

section .init.data              ; 开启分页前临时的数据段

stack:    times 1024 db 0       ; 这里作为临时内核栈
STACK_TOP equ $-stack-1         ; 内核栈顶,$ 符指代是当前地址

mboot_ptr_tmp: dd 0             ; 全局的 multiboot 结构体指针

;-----------------------------------------------------------------------------


================================================
FILE: arch/i386/intr/intr.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  intr.c
 *
 *    Description:  中断描述符表相关
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 14时45分36秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <debug.h>
#include <arch.h>
#include <common.h>

#define INTERRUPT_MAX 256

// 中断描述符
typedef
struct idt_entry_t {
        uint16_t base_lo;        // 中断处理函数地址 15~0 位
        uint16_t sel;            // 目标代码段描述符选择子
        uint8_t  always0;        // 置 0 段
        uint8_t  flags;          // 一些标志,文档有解释
        uint16_t base_hi;        // 中断处理函数地址 31~16 位
}__attribute__((packed)) idt_entry_t;

// IDTR
typedef
struct idt_ptr_t {
        uint16_t limit;        // 限长
        uint32_t base;         // 基址
} __attribute__((packed)) idt_ptr_t;

// 中断描述符表
static idt_entry_t idt_entries[INTERRUPT_MAX] __attribute__ ((aligned(16)));

// IDTR
static idt_ptr_t idt_ptr;

// 中断处理函数的指针数组
static interrupt_handler_t interrupt_handlers[INTERRUPT_MAX] __attribute__ ((aligned(4)));

// 设置中断描述符
static void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags);

// 声明加载 IDTR 的函数
extern void idt_flush(uint32_t);

// 中断处理函数指针类型
typedef void (*isr_irq_func_t)();

// 中断处理函数指针数组
static isr_irq_func_t isr_irq_func[INTERRUPT_MAX] = {
        [0]  = &isr0,  [1]  = &isr1,  [2]  = &isr2,  [3]  = &isr3,
        [4]  = &isr4,  [5]  = &isr5,  [6]  = &isr6,  [7]  = &isr7,
        [8]  = &isr8,  [9]  = &isr9,  [10] = &isr10, [11] = &isr11,
        [12] = &isr12, [13] = &isr13, [14] = &isr14, [15] = &isr15,
        [16] = &isr16, [17] = &isr17, [18] = &isr18, [19] = &isr19,
        [20] = &isr20, [21] = &isr21, [22] = &isr22, [23] = &isr23,
        [24] = &isr24, [25] = &isr25, [26] = &isr26, [27] = &isr27,
        [28] = &isr28, [29] = &isr29, [30] = &isr30, [31] = &isr31, 

        [32] = &irq0,  [33] = &irq1,  [34] = &irq2,  [35] = &irq3,
        [36] = &irq4,  [37] = &irq5,  [38] = &irq6,  [39] = &irq7,
        [40] = &irq8,  [41] = &irq9,  [42] = &irq10, [43] = &irq11,
        [44] = &irq12, [45] = &irq13, [46] = &irq14, [47] = &irq15, 
};

// 初始化中断描述符表
void idt_init(void)
{
        init_interrupt_chip();

        idt_ptr.limit = sizeof(idt_entry_t) * INTERRUPT_MAX - 1;
        idt_ptr.base  = (uint32_t)&idt_entries;

        // 0~31:  用于 CPU 的中断处理
        // 32~47: Intel 保留
        for (uint32_t i = 0; i < 48; ++i) {
                idt_set_gate(i, (uint32_t)isr_irq_func[i], 0x08, 0x8E);
        }

        // 128 (0x80) 将来用于实现系统调用
        idt_set_gate(128, (uint32_t)isr128, 0x08, 0xEF);

        // 更新设置中断描述符表
        idt_flush((uint32_t)&idt_ptr);
}

// 设置中断描述符
static void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags)
{
        idt_entries[num].base_lo = base & 0xFFFF;
        idt_entries[num].base_hi = (base >> 16) & 0xFFFF;

        idt_entries[num].sel = sel;
        idt_entries[num].always0 = 0;

        idt_entries[num].flags = flags;
}

static const char *intrname(uint32_t intrno)
{
        static const char *const intrnames[] = {
                "Divide error",
                "Debug",
                "Non-Maskable Interrupt",
                "Breakpoint",
                "Overflow",
                "BOUND Range Exceeded",
                "Invalid Opcode",
                "Device Not Available",
                "Double Fault",
                "Coprocessor Segment Overrun",
                "Invalid TSS",
                "Segment Not Present",
                "Stack Fault",
                "General Protection",
                "Page Fault",
                "(unknown trap)",
                "x87 FPU Floating-Point Error",
                "Alignment Check",
                "Machine-Check",
                "SIMD Floating-Point Exception"
        };

        if (intrno < sizeof(intrnames)/sizeof(const char *const)) {
                return intrnames[intrno];
        }

        return "(unknown trap)";
}

// 调用中断处理函数
void isr_handler(pt_regs_t *regs)
{
        if (interrupt_handlers[regs->int_no]) {
              interrupt_handlers[regs->int_no](regs);
        } else {
                cprintk(rc_black, rc_blue, "Unhandled interrupt: %d %s\n", regs->int_no, intrname(regs->int_no));
                cpu_hlt();
        }
}

// 注册一个中断处理函数
void register_interrupt_handler(uint8_t n, interrupt_handler_t h)
{
        interrupt_handlers[n] = h;
}

// IRQ 处理函数
void irq_handler(pt_regs_t *regs)
{
        // 重设PIC芯片
	clear_interrupt_chip(regs->int_no);

        if (interrupt_handlers[regs->int_no]) {
                interrupt_handlers[regs->int_no](regs);
        }
}



================================================
FILE: arch/i386/intr/intr.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  intr.h
 *
 *    Description:  中断描述符表相关
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 14时49分48秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef IDT_H_
#define IDT_H_

#include <types.h>

// 中断保存的寄存器类型
typedef
struct pt_regs_t {

        // 用于保存用户的数据段描述符
        uint16_t ds;
        uint16_t padding1;

        // 从 edi 到 eax 由 pusha 指令压栈
        uint32_t edi;
        uint32_t esi;
        uint32_t ebp;
        uint32_t oesp;
        uint32_t ebx;
        uint32_t edx;
        uint32_t ecx;
        uint32_t eax;

        // 中断号(内核代码自行压栈)
        uint32_t int_no;

        // 错误代码(有中断错误代码的中断会由CPU压栈)
        uint32_t err_code;

        // 以下由处理器自动压栈
        uint32_t eip;
        uint16_t cs;
        uint16_t padding2;
        uint32_t eflags;

        // 如果发生了特权级的切换CPU会压栈
        uint32_t esp;
        uint16_t ss;
        uint16_t padding3;
} pt_regs_t;

// 定义中断处理函数指针
typedef void (*interrupt_handler_t)(pt_regs_t *);

// 调用中断处理函数
void isr_handler(pt_regs_t *regs);

// 注册一个中断处理函数
void register_interrupt_handler(uint8_t n, interrupt_handler_t h);

// 中断号定义
#define INT_DIVIDE_ERROR         0
#define INT_DEBUG                1
#define INT_NMI                  2
#define INT_BREAKPOINT           3
#define INT_OVERFLOW             4
#define INT_BOUND                5
#define INT_INVALID_OPCODE       6
#define INT_DEVICE_NOT_AVAIL     7
#define INT_DOUBLE_FAULT         8
#define INT_COPROCESSOR          9
#define INT_INVALID_TSS         10
#define INT_SEGMENT             11
#define INT_STACK_FAULT         12
#define INT_GENERAL_PROTECT     13
#define INT_PAGE_FAULT          14

#define INT_X87_FPU             16
#define INT_ALIGNMENT           17
#define INT_MACHINE_CHECK       18
#define INT_SIMD_FLOAT          19
#define INT_VIRTUAL_EXCE        20

// 声明中断处理函数 0-19 属于 CPU 的异常中断
// ISR:中断服务程序(interrupt service routine)
void isr0();            // 0 #DE 除 0 异常 
void isr1();            // 1 #DB 调试异常 
void isr2();            // 2 NMI 
void isr3();            // 3 BP 断点异常 
void isr4();            // 4 #OF 溢出 
void isr5();            // 5 #BR 对数组的引用超出边界 
void isr6();            // 6 #UD 无效或未定义的操作码 
void isr7();            // 7 #NM 设备不可用(无数学协处理器) 
void isr8();            // 8 #DF 双重故障(有错误代码) 
void isr9();            // 9 协处理器跨段操作 
void isr10();           // 10 #TS 无效TSS(有错误代码) 
void isr11();           // 11 #NP 段不存在(有错误代码) 
void isr12();           // 12 #SS 栈错误(有错误代码) 
void isr13();           // 13 #GP 常规保护(有错误代码) 
void isr14();           // 14 #PF 页故障(有错误代码) 
void isr15();           // 15 CPU 保留 
void isr16();           // 16 #MF 浮点处理单元错误 
void isr17();           // 17 #AC 对齐检查 
void isr18();           // 18 #MC 机器检查 
void isr19();           // 19 #XM SIMD(单指令多数据)浮点异常

// 20-31 Intel 保留
void isr20();
void isr21();
void isr22();
void isr23();
void isr24();
void isr25();
void isr26();
void isr27();
void isr28();
void isr29();
void isr30();
void isr31();

// 32~255 用户自定义异常
void isr128();

// IRQ 处理函数
void irq_handler(pt_regs_t *regs);

// 定义IRQ
#define  IRQ0     32    // 电脑系统计时器
#define  IRQ1     33    // 键盘
#define  IRQ2     34    // 与 IRQ9 相接,MPU-401 MD 使用
#define  IRQ3     35    // 串口设备
#define  IRQ4     36    // 串口设备
#define  IRQ5     37    // 建议声卡使用
#define  IRQ6     38    // 软驱传输控制使用
#define  IRQ7     39    // 打印机传输控制使用
#define  IRQ8     40    // 即时时钟
#define  IRQ9     41    // 与 IRQ2 相接,可设定给其他硬件
#define  IRQ10    42    // 建议网卡使用
#define  IRQ11    43    // 建议 AGP 显卡使用
#define  IRQ12    44    // 接 PS/2 鼠标,也可设定给其他硬件
#define  IRQ13    45    // 协处理器使用
#define  IRQ14    46    // IDE0 传输控制使用
#define  IRQ15    47    // IDE1 传输控制使用

// 声明 IRQ 函数
// IRQ:中断请求(Interrupt Request)
void irq0();            // 电脑系统计时器
void irq1();            // 键盘
void irq2();            // 与 IRQ9 相接,MPU-401 MD 使用
void irq3();            // 串口设备
void irq4();            // 串口设备
void irq5();            // 建议声卡使用
void irq6();            // 软驱传输控制使用
void irq7();            // 打印机传输控制使用
void irq8();            // 即时时钟
void irq9();            // 与 IRQ2 相接,可设定给其他硬件
void irq10();           // 建议网卡使用
void irq11();           // 建议 AGP 显卡使用
void irq12();           // 接 PS/2 鼠标,也可设定给其他硬件
void irq13();           // 协处理器使用
void irq14();           // IDE0 传输控制使用
void irq15();           // IDE1 传输控制使用

// 初始化中断描述符表
void idt_init(void);

#endif  // IDT_H_


================================================
FILE: arch/i386/intr/intr_s.s
================================================
; --------------------------------------------------
; 	将 IDT 地址 载入 IDTR
;
; 	qianyi.lh  2014/11/04  14:44:23
;---------------------------------------------------

[GLOBAL idt_flush]
idt_flush:
	mov eax, [esp+4]           ; 参数存入 eax 寄存器
	lidt [eax]                 ; 加载到 IDTR
	ret
.end:

; 定义两个构造中断处理函数的宏(有的中断有错误代码,有的没有)
; 用于没有错误代码的中断
%macro ISR_NOERRCODE 1
[GLOBAL isr%1]
isr%1:
	push 0                      ; push 无效的中断错误代码(起到占位作用,便于所有isr函数统一清栈)
	push %1                     ; push 中断号
	jmp isr_common_stub
%endmacro

; 用于有错误代码的中断
%macro ISR_ERRCODE 1
[GLOBAL isr%1]
isr%1:
	push %1                     ; push 中断号
	jmp isr_common_stub
%endmacro

; 定义中断处理函数
ISR_NOERRCODE  0 	; 0 #DE 除 0 异常
ISR_NOERRCODE  1 	; 1 #DB 调试异常
ISR_NOERRCODE  2 	; 2 NMI
ISR_NOERRCODE  3 	; 3 BP 断点异常 
ISR_NOERRCODE  4 	; 4 #OF 溢出 
ISR_NOERRCODE  5 	; 5 #BR 对数组的引用超出边界 
ISR_NOERRCODE  6 	; 6 #UD 无效或未定义的操作码 
ISR_NOERRCODE  7 	; 7 #NM 设备不可用(无数学协处理器) 
ISR_ERRCODE    8 	; 8 #DF 双重故障(有错误代码) 
ISR_NOERRCODE  9 	; 9 协处理器跨段操作
ISR_ERRCODE   10 	; 10 #TS 无效TSS(有错误代码) 
ISR_ERRCODE   11 	; 11 #NP 段不存在(有错误代码) 
ISR_ERRCODE   12 	; 12 #SS 栈错误(有错误代码) 
ISR_ERRCODE   13 	; 13 #GP 常规保护(有错误代码) 
ISR_ERRCODE   14 	; 14 #PF 页故障(有错误代码) 
ISR_NOERRCODE 15 	; 15 CPU 保留 
ISR_NOERRCODE 16 	; 16 #MF 浮点处理单元错误 
ISR_ERRCODE   17 	; 17 #AC 对齐检查 
ISR_NOERRCODE 18 	; 18 #MC 机器检查 
ISR_NOERRCODE 19 	; 19 #XM SIMD(单指令多数据)浮点异常

; 20~31 Intel 保留
ISR_NOERRCODE 20
ISR_NOERRCODE 21
ISR_NOERRCODE 22
ISR_NOERRCODE 23
ISR_NOERRCODE 24
ISR_NOERRCODE 25
ISR_NOERRCODE 26
ISR_NOERRCODE 27
ISR_NOERRCODE 28
ISR_NOERRCODE 29
ISR_NOERRCODE 30
ISR_NOERRCODE 31

; 32~255 用户自定义
ISR_NOERRCODE 128               ; 0x80 syscall

[GLOBAL isr_common_stub]
[EXTERN isr_handler]
; 中断服务程序
isr_common_stub:
	pusha                   ; Pushes edi, esi, ebp, esp, ebx, edx, ecx, eax
	mov ax, ds
	push eax                ; 保存数据段描述符
	
	mov ax, 0x10            ; 加载内核数据段描述符表
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov ss, ax
	
	push esp		; 此时的 esp 寄存器的值等价于 pt_regs 结构体的指针
	call isr_handler        ; 在 C 语言代码里
	add esp, 4 		; 清除压入的参数
	
	pop ebx                 ; 恢复原来的数据段描述符
	mov ds, bx
	mov es, bx
	mov fs, bx
	mov gs, bx
	mov ss, bx
	
	popa                     ; Pops edi, esi, ebp, esp, ebx, edx, ecx, eax
	add esp, 8               ; 清理栈里的 error code 和 ISR
	iret
.end:


; 构造中断请求的宏
%macro IRQ 2
[GLOBAL irq%1]
irq%1:
	push 0
	push %2
	jmp irq_common_stub
%endmacro

IRQ   0,    32 	; 电脑系统计时器
IRQ   1,    33 	; 键盘
IRQ   2,    34 	; 与 IRQ9 相接,MPU-401 MD 使用
IRQ   3,    35 	; 串口设备
IRQ   4,    36 	; 串口设备
IRQ   5,    37 	; 建议声卡使用
IRQ   6,    38 	; 软驱传输控制使用
IRQ   7,    39 	; 打印机传输控制使用
IRQ   8,    40 	; 即时时钟
IRQ   9,    41 	; 与 IRQ2 相接,可设定给其他硬件
IRQ  10,    42 	; 建议网卡使用
IRQ  11,    43 	; 建议 AGP 显卡使用
IRQ  12,    44 	; 接 PS/2 鼠标,也可设定给其他硬件
IRQ  13,    45 	; 协处理器使用
IRQ  14,    46 	; IDE0 传输控制使用
IRQ  15,    47 	; IDE1 传输控制使用

[GLOBAL irq_common_stub]
[GLOBAL forkret_s]
[EXTERN irq_handler]
irq_common_stub:
	pusha                    ; pushes edi, esi, ebp, esp, ebx, edx, ecx, eax
	
	mov ax, ds
	push eax                 ; 保存数据段描述符
	
	mov ax, 0x10  		 ; 加载内核数据段描述符
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov ss, ax
	
	push esp
	call irq_handler
	add esp, 4

forkret_s:
	pop ebx                   ; 恢复原来的数据段描述符
	mov ds, bx
	mov es, bx
	mov fs, bx
	mov gs, bx
	mov ss, bx
	
	popa                     ; Pops edi,esi,ebp...
	add esp, 8     		 ; 清理压栈的 错误代码 和 ISR 编号
	iret          		 ; 出栈 CS, EIP, EFLAGS, SS, ESP
.end:



================================================
FILE: arch/i386/mm/fault.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  fault.c
 *
 *    Description:  页错误处理
 *
 *        Version:  1.0
 *        Created:  2014年11月05日 09时58分02秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <mm/mm.h>
#include <common.h>
#include <debug.h>
#include <arch.h>

void do_page_fault(pt_regs_t *regs)
{
        uint32_t cr2;
        __asm__ volatile ("mov %%cr2, %0" : "=r" (cr2));

        printk("Page fault at EIP: 0x%x, virtual faulting address 0x%x\n", regs->eip, cr2);
        printk("Error code: %x\n", regs->err_code);

        // bit 0 为 0 指页面不存在内存里
        if ( !(regs->err_code & 0x1)) {
                cprintk(rc_black, rc_red, "Because the page wasn't present.\n");
        }
        // bit 1 为 0 表示读错误,为 1 为写错误
        if (regs->err_code & 0x2) {
                cprintk(rc_black, rc_red, "Write error.\n");
        } else {
                cprintk(rc_black, rc_red, "Read error.\n");
        }
        // bit 2 为 1 表示在用户模式打断的,为 0 是在内核模式打断的
        if (regs->err_code & 0x4) {
                cprintk(rc_black, rc_red, "In user mode.\n");
        } else {
                cprintk(rc_black, rc_red, "In kernel mode.\n");
        }
        // bit 3 为 1 表示错误是由保留位覆盖造成的
        if (regs->err_code & 0x8) {
                cprintk(rc_black, rc_red, "Reserved bits being overwritten.\n");
        }
        // bit 4 为 1 表示错误发生在取指令的时候
        if (regs->err_code & 0x10) {
                cprintk(rc_black, rc_red, "The fault occurred during an instruction fetch.\n");
        }

        while (1) {
                cpu_hlt();
        }
}



================================================
FILE: arch/i386/mm/gdt.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  gdt.c
 *
 *    Description:  全局描述符表相关
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 14时13分14秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include "gdt.h"

// 全局描述符类型
typedef
struct gdt_entry_t {
        uint16_t limit_low;     // 段界限   15~0
        uint16_t base_low;      // 段基地址 15~0
        uint8_t  base_middle;   // 段基地址 23~16
        uint8_t  access;        // 段存在位、描述符特权级、描述符类型、描述符子类别
        uint8_t  granularity;   // 其他标志、段界限 19~16
        uint8_t  base_high;     // 段基地址 31~24
} __attribute__((packed)) gdt_entry_t;

// 全局描述符表定义
static gdt_entry_t gdt_entries[GDT_LENGTH] __attribute__ ((aligned(8)));

static void gdt_set_gate(int32_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran)
{
        gdt_entries[num].base_low     = (base & 0xFFFF);
        gdt_entries[num].base_middle  = (base >> 16) & 0xFF;
        gdt_entries[num].base_high    = (base >> 24) & 0xFF;

        gdt_entries[num].limit_low    = (limit & 0xFFFF);
        gdt_entries[num].granularity  = (limit >> 16) & 0x0F;

        gdt_entries[num].granularity |= gran & 0xF0;
        gdt_entries[num].access       = access;
}

// TSS 段定义
static tss_entry_t tss_entry __attribute__ ((aligned(8)));

static void tss_set_gate(int32_t num, uint16_t ss0, uint32_t esp0)
{
	// 获取 TSS 描述符的位置和长度
	uint32_t base = (uint32_t)&tss_entry;
	uint32_t limit = base + sizeof(tss_entry);

	// 在 GDT 表中增加 TSS 段描述
	gdt_set_gate(num, base, limit, 0x89, 0x40);

	// 设置内核栈的地址
	tss_entry.ts_ss0  = ss0;
	tss_entry.ts_esp0 = esp0;

        tss_entry.ts_cs = USER_CS;
	tss_entry.ts_ss = USER_DS;
	tss_entry.ts_ds = USER_DS;
	tss_entry.ts_es = USER_DS;
	tss_entry.ts_fs = USER_DS;
	tss_entry.ts_gs = USER_DS;
}

// GDTR
typedef
struct gdt_ptr_t {
        uint16_t limit;         // 全局描述符表限长
        uint32_t base;          // 全局描述符表 32位 基地址
} __attribute__((packed)) gdt_ptr_t;

// GDTR
static gdt_ptr_t gdt_ptr;

// 初始化全局描述符表
void gdt_init(void)
{
        // 全局描述符表界限  从 0 开始,所以总长要 - 1
        gdt_ptr.limit = sizeof(gdt_entry_t) * GDT_LENGTH - 1;
        gdt_ptr.base = (uint32_t)&gdt_entries;
        
        // 采用 Intel 平坦模型
        gdt_set_gate(SEG_NULL,  0x0, 0x0, 0x0, 0x0);            // Intel文档要求首个描述符全0
        gdt_set_gate(SEG_KTEXT, 0x0, 0xFFFFFFFF, 0x9A, 0xC0);   // 内核指令段
        gdt_set_gate(SEG_KDATA, 0x0, 0xFFFFFFFF, 0x92, 0xC0);   // 内核数据段
        gdt_set_gate(SEG_UTEXT, 0x0, 0xFFFFFFFF, 0xFA, 0xC0);   // 用户模式代码段
        gdt_set_gate(SEG_UDATA, 0x0, 0xFFFFFFFF, 0xF2, 0xC0);   // 用户模式数据段
        
        tss_set_gate(SEG_TSS, KERNEL_DS, 0);
        
        // 加载全局描述符表地址到 GPTR 寄存器
        gdt_flush((uint32_t)&gdt_ptr);
        
        // 加载任务寄存器
	tss_flush();
}



================================================
FILE: arch/i386/mm/gdt.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  gdt.h
 *
 *    Description:  全局描述符表支持
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 14时11分51秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef GDT_H_
#define GDT_H_

#include <types.h>

// 全局描述符表长度
#define GDT_LENGTH 6

// 各个内存段所在全局描述符表下标
#define SEG_NULL    0
#define SEG_KTEXT   1
#define SEG_KDATA   2
#define SEG_UTEXT   3
#define SEG_UDATA   4
#define SEG_TSS     5

#define GD_KTEXT    ((SEG_KTEXT) << 3)      // 内核代码段
#define GD_KDATA    ((SEG_KDATA) << 3)      // 内核数据段
#define GD_UTEXT    ((SEG_UTEXT) << 3)      // 用户代码段
#define GD_UDATA    ((SEG_UDATA) << 3)      // 用户数据段
#define GD_TSS      ((SEG_TSS) << 3)        // 任务段

// 段描述符 DPL
#define DPL_KERNEL  (0)
#define DPL_USER    (3)

// 各个段的全局描述符表的选择子
#define KERNEL_CS   ((GD_KTEXT) | DPL_KERNEL)
#define KERNEL_DS   ((GD_KDATA) | DPL_KERNEL)
#define USER_CS     ((GD_UTEXT) | DPL_USER)
#define USER_DS     ((GD_UDATA) | DPL_USER)

// TSS 描述符
typedef
struct tss_entry_t {
        uint32_t ts_link;         // old ts selector
        uint32_t ts_esp0;         // stack pointers and segment selectors
        uint16_t ts_ss0;          // after an increase in privilege level
        uint16_t ts_padding1;
        uint32_t ts_esp1;
        uint16_t ts_ss1;
        uint16_t ts_padding2;
        uint32_t ts_esp2;
        uint16_t ts_ss2;
        uint16_t ts_padding3;
        uint32_t ts_cr3;          // page directory base
        uint32_t ts_eip;          // saved state from last task switch
        uint32_t ts_eflags;
        uint32_t ts_eax;          // more saved state (registers)
        uint32_t ts_ecx;
        uint32_t ts_edx;
        uint32_t ts_ebx;
        uint32_t ts_esp;
        uint32_t ts_ebp;
        uint32_t ts_esi;
        uint32_t ts_edi;
        uint16_t ts_es;           // even more saved state (segment selectors)
        uint16_t ts_padding4;
        uint16_t ts_cs;
        uint16_t ts_padding5;
        uint16_t ts_ss;
        uint16_t ts_padding6;
        uint16_t ts_ds;
        uint16_t ts_padding7;
        uint16_t ts_fs;
        uint16_t ts_padding8;
        uint16_t ts_gs;
        uint16_t ts_padding9;
        uint16_t ts_ldt;
        uint16_t ts_padding10;
        uint16_t ts_t;            // trap on task switch
        uint16_t ts_iomb;         // i/o map base address
} __attribute__((packed)) tss_entry_t;

// 初始化全局描述符表
void gdt_init(void);

// GDT 加载到 GDTR 的函数
extern void gdt_flush();

// TSS 刷新[汇编实现]
extern void tss_flush();

#endif  // GDT_H_


================================================
FILE: arch/i386/mm/gdt_s.s
================================================
; -------------------------------------------------
;       GDTR 和 TR 相关操作
;
;       qianyi.lh  2014/11/04  14:15:54
; -------------------------------------------------

[GLOBAL gdt_flush]

gdt_flush:
        mov eax, [esp+4]  ; 参数存入 eax 寄存器
        lgdt [eax]        ; 加载到 GDTR [修改原先GRUB设置]

        mov ax, 0x10      ; 加载数据段描述符
        mov ds, ax        ; 更新所有可以更新的段寄存器
        mov es, ax
        mov fs, ax
        mov gs, ax
        mov ss, ax
        jmp 0x08:.flush   ; 远跳转,0x08是代码段描述符
                          ; 远跳目的是清空流水线并串行化处理器
.flush:
        ret

[GLOBAL tss_flush]        ; TSS 刷新
tss_flush:
        mov ax, 0x28      ; TSS 在全局描述符表里是第5个
       		          ; 故而 00101000B 即就是 0x28
        ltr ax            ; 加载到 TR 寄存器
        ret



================================================
FILE: arch/i386/mm/pmm.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  pmm.c
 *
 *    Description:  物理内存管理
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 13时13分04秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <mboot.h>
#include <types.h>
#include <debug.h>
#include <sync.h>
#include <mm/mm.h>
#include <mm/ff_mm.h>
#include <mm/buddy_mm.h>
#include <lib/string.h>

// 物理内存管理算法
static const struct pmm_manager *pmm_manager = &ff_mm_manager;

// 物理页帧数组指针 (内核结束地址[实地址]+内核基址+内核页表保留地址)
static page_t *phy_pages = (page_t *)((uint32_t)kern_end + KERNBASE + KVPAGE_SIZE);

// 物理页帧数组长度
static uint32_t phy_pages_count;

// 可用物理内存页起始地址
static uint32_t pmm_addr_start;

// 可用物理内存页结束地址
static uint32_t pmm_addr_end;

// 获取可用内存的起始和结束地址
static void get_ram_info(e820map_t *e820map);

// 物理内存页初始化
static void phy_pages_init(e820map_t *e820map);

void pmm_init(void)
{
	show_kernel_memory_map();
	
        e820map_t e820map;
        bzero(&e820map, sizeof(e820map));
        
        get_ram_info(&e820map);
        phy_pages_init(&e820map);
        
        page_init(phy_pages, phy_pages_count);
}

static void get_ram_info(e820map_t *e820map)
{
        mmap_entry_t *mmap_start_addr = (mmap_entry_t *)glb_mboot_ptr->mmap_addr;
        mmap_entry_t *mmap_end_addr = (mmap_entry_t *)glb_mboot_ptr->mmap_addr + glb_mboot_ptr->mmap_length;

        mmap_entry_t *map_entry;
        for (map_entry = mmap_start_addr; map_entry < mmap_end_addr; map_entry++) {
                if (map_entry->type == MULTIBOOT_TYPE_RAM && map_entry->base_addr_low == RAM_KERNEL_START) {
                        e820map->map[e820map->count].addr_low = map_entry->base_addr_low;
                        e820map->map[e820map->count].addr_high = map_entry->base_addr_high;
                        e820map->map[e820map->count].length_low = map_entry->length_low;
                        e820map->map[e820map->count].length_high = map_entry->length_high;
                        e820map->map[e820map->count].type = E820_ARM;
                        e820map->count++;
                }
        }
}

static void phy_pages_init(e820map_t *e820map)
{
        uint32_t phy_mem_length = 0;
        for (uint32_t i = 0; i < e820map->count; ++i){
                if (e820map->map[i].addr_low > ZONE_HIGHMEM_ADDR) {
                      break;
                }
                if (e820map->map[i].addr_low + e820map->map[i].length_low > ZONE_HIGHMEM_ADDR) {
                        phy_mem_length = ZONE_HIGHMEM_ADDR;
                        break;
                }
                phy_mem_length += e820map->map[i].length_low;
        }

        uint32_t pages_mem_length = sizeof(page_t) * (phy_mem_length / PMM_PAGE_SIZE);
        bzero(phy_pages, pages_mem_length);

        // 物理内存页管理起始地址
        pmm_addr_start = ((uint32_t)phy_pages - KERNBASE + pages_mem_length + PMM_PAGE_SIZE) & PMM_PAGE_MASK;

        for (uint32_t i = 0; i < e820map->count; ++i){
                uint32_t start_addr = e820map->map[i].addr_low;
                uint32_t end_addr = e820map->map[i].addr_low + e820map->map[i].length_low;
                if (start_addr < pmm_addr_start) {
                        start_addr = pmm_addr_start;
                }
                if (end_addr > ZONE_HIGHMEM_ADDR) {
                        end_addr = ZONE_HIGHMEM_ADDR;
                }
                for (uint32_t addr = start_addr; addr < end_addr; addr += PMM_PAGE_SIZE) {
                        phy_pages_count++;
                }
                pmm_addr_end = end_addr;
        }

        assert(pmm_addr_start == page_to_addr(&phy_pages[0]),
                        "phy_pages_init error pmm_start != &page[0]");
        assert(pmm_addr_end - PMM_PAGE_SIZE == page_to_addr(&phy_pages[phy_pages_count-1]),
                        "phy_pages_init error pmm_end != &page[n-1]");
        assert(&phy_pages[0] == addr_to_page(page_to_addr(&phy_pages[0])),
                        "phy_pages_init error addr_to_page error");
        assert(&phy_pages[1] == addr_to_page(page_to_addr(&phy_pages[1])),
                        "phy_pages_init error addr_to_page error");
}

page_t *addr_to_page(uint32_t addr)
{
        assert(pmm_addr_start != 0, "memory not init, addr_to_page cannot use");

        return (phy_pages + ((addr & PMM_PAGE_MASK) - pmm_addr_start) / PMM_PAGE_SIZE);
}

uint32_t page_to_addr(page_t *page)
{
        assert(pmm_addr_start != 0, "memory not init, addr_to_page cannot use");
        
        return (pmm_addr_start + (uint32_t)(page - phy_pages) * PMM_PAGE_SIZE);
}

void page_init(page_t *pages, uint32_t n)
{
        pmm_manager->page_init(pages, n);
}

uint32_t alloc_pages(uint32_t n)
{
        uint32_t page;
        uint32_t eflag;
        
        local_intr_store(eflag);
        page = pmm_manager->alloc_pages(n);
        local_intr_restore(eflag);

        return page;
}

void free_pages(uint32_t addr, uint32_t n)
{
        uint32_t eflag;
        
        local_intr_store(eflag);
        pmm_manager->free_pages(addr, n);
        local_intr_restore(eflag);
}

uint32_t free_pages_count(void)
{
        return pmm_manager->free_pages_count();
}



================================================
FILE: arch/i386/mm/pmm.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  pmm.h
 *
 *    Description:  物理内存管理
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 13时03分24秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_MM_PMM_H
#define INCLUDE_MM_PMM_H

#include <types.h>
#include <atomic.h>

// 默认栈的大小(4096)
#define STACK_SIZE     (0x1000)

// 物理内存页框大小 
#define PMM_PAGE_SIZE  (0x1000)

// 页掩码 按照 0x1000(4096) 对齐地址
#define PMM_PAGE_MASK  (0xFFFFF000)

// 内核在物理内存起始位置
#define RAM_KERNEL_START (0x100000)

// 内核代码在内存中的起始和结束位置,在链接脚本中定义
extern uint8_t kern_start[];
extern uint8_t kern_end[];

// 开启分页机制之后的内核栈
extern uint8_t kern_stack[STACK_SIZE];

// 内核栈的栈顶
extern uint32_t kern_stack_top;

// BIOS int 0x15 AX = 0xE820 常量
#define E820MAX             (20)      // 最大的表项数目
#define E820_ARM            (1)       // 可用 RAM
#define E820_ARR            (2)       // 保留区域

typedef
struct e820map_t {
        uint32_t count;
        struct {
                uint32_t addr_low;
                uint32_t addr_high;
                uint32_t length_low;
                uint32_t length_high;
                uint32_t type;
        } __attribute__((packed)) map[E820MAX];
} e820map_t;

// 内存页类型
typedef
enum mem_zone_t {
        ZONE_DMA = 0,
        ZONE_NORMAL = 1,
        ZONE_HIGHMEM = 2
} mem_zone_t;

#define ZONE_NORMAL_ADDR     (0x1000000)   // 16 MB
#define ZONE_HIGHMEM_ADDR    (0x38000000)  // 896 MB

// 物理页结构
typedef
struct page_t {
        atomic_t ref;                // 物理页被引用的次数
        uint32_t flag;               // 当前页状态
        union {
                uint32_t ncount;     // 当前页后续连续页的数量  First-Fit算法需要
                uint32_t order;      // 当前页的 order 值       buddy 算法需要
        };
        struct list_head list;       // 链接下一个连续页
} page_t;

// page_t 的 flag 参数的操作宏
#define PG_RESERVED     (0)       // 1 << 0 表示页当前不可用
#define PG_NCOUNT       (1)       // 1 << 1 表示 ncount 字段有效
#define PG_ORDER        (2)       // 1 << 2 表示 order 字段有效

#define set_page_reserved_flag(page)       set_bit(PG_RESERVED, &((page)->flag))
#define clear_page_reserved_flag(page)     clear_bit(PG_RESERVED, &((page)->flag))
#define is_page_reserved(page)             test_bit(PG_RESERVED, &((page)->flag))

#define set_page_ncount_flag(page)          set_bit(PG_NCOUNT, &((page)->flag))
#define clear_page_ncount_flag(page)        clear_bit(PG_NCOUNT, &((page)->flag))
#define is_page_ncount(page)                test_bit(PG_NCOUNT, &((page)->flag))

#define set_page_order_flag(page)          set_bit(PG_ORDER, &((page)->flag))
#define clear_page_order_flag(page)        clear_bit(PG_ORDER, &((page)->flag))
#define is_page_order(page)                test_bit(PG_ORDER, &((page)->flag))

static inline int32_t page_ref(page_t *page)
{
        return atomic_read(&page->ref);
}

static inline void set_page_ref(page_t *page, int32_t val)
{
        atomic_set(&page->ref, val);
}

static inline void page_ref_inc(page_t *page)
{
        atomic_inc(&page->ref);
}

static inline void page_ref_dec(page_t *page)
{
        atomic_dec(&page->ref);
}

// 由物理地址计算出该地址所处页的管理结构的指针
page_t *addr_to_page(uint32_t addr);

// 由页的管理结构的指针计算出页所在物理地址
uint32_t page_to_addr(page_t *page);

// 内存管理子系统管理对象
struct pmm_manager {
        const char *name;                                // 管理算法的名称
        void (*page_init)(page_t *pages, uint32_t n);    // 初始化
        uint32_t (*alloc_pages)(uint32_t n);             // 申请物理内存页(n为字节数)
        void (*free_pages)(uint32_t addr, uint32_t n);   // 释放内存页
        uint32_t (*free_pages_count)(void);              // 返回当前可用内存页
};

// 物理内存管理初始化
void pmm_init(void);

// 内存管理算法初始化
void page_init(page_t *pages, uint32_t n);

// 申请内存页
uint32_t alloc_pages(uint32_t n);

// 释放内存页
void free_pages(uint32_t addr, uint32_t n);

#define alloc_page alloc_pages(1)
#define free_page(addr) free_pages(addr, 1)

// 当前可用内存页
uint32_t free_pages_count(void);

#endif  // INCLUDE_MM_PMM_H


================================================
FILE: arch/i386/mm/vmm.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  vmm.c
 *
 *    Description:  虚拟内存管理
 *
 *        Version:  1.0
 *        Created:  2014年11月05日 09时55分49秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <arch.h>
#include <common.h>
#include <debug.h>
#include <mm/mm.h>
#include <lib/string.h>

// 内核页目录
pgd_t pgd_kern[PGD_SIZE] __attribute__ ((aligned(PAGE_SIZE)));

// 内核页表起始
static pte_t *pte_addr = (pte_t *)((uint32_t)kern_end + KERNBASE);

void vmm_init(void)
{
        // 注册页错误中断的处理函数 
        register_interrupt_handler(INT_PAGE_FAULT, &do_page_fault);
        
        // 页表数组指针
        pte_t (*pte_kern)[PTE_SIZE] = (pte_t (*)[PTE_SIZE])pte_addr;

        // 构造页目录(MMU需要的是物理地址,此处需要减去偏移)
        uint32_t pgd_idx = PGD_INDEX(PAGE_OFFSET);
        for (uint32_t i = pgd_idx; i < pgd_idx + PTE_COUNT; ++i) {
                pgd_kern[i] = ((uint32_t)ka_to_pa(pte_kern[i])) | PAGE_PRESENT | PAGE_WRITE;
        }

        // 构造页表映射,内核 0xC0000000~0xF8000000 映射到 物理 0x00000000~0x38000000 (物理内存前896MB)
        uint32_t *pte_start = (uint32_t *)(pte_addr + PTE_SIZE * pgd_idx);
        for (uint32_t i = 0; i < PTE_SIZE * PTE_COUNT; ++i) {
                pte_start[i] = (i << 12) | PAGE_PRESENT | PAGE_WRITE;
        }

        switch_pgd((uint32_t)ka_to_pa(pgd_kern));
}

void map(pgd_t *pgd_now, uint32_t va, uint32_t pa, uint32_t flags)
{       
        uint32_t pgd_idx = PGD_INDEX(va);
        uint32_t pte_idx = PTE_INDEX(va); 
        
        pte_t *pte = (pte_t *)(pgd_now[pgd_idx] & PAGE_MASK);
        if (!pte) {
                pte = (pte_t *)alloc_pages(1);
                pgd_now[pgd_idx] = (uint32_t)pte | PAGE_PRESENT | PAGE_WRITE;
                pte = (pte_t *)pa_to_ka(pte);
        } else {
                pte = (pte_t *)pa_to_ka(pte);
        }

        pte[pte_idx] = (pa & PAGE_MASK) | flags;

        tlb_reload_page(va);
}

void unmap(pgd_t *pgd_now, uint32_t va)
{
        uint32_t pgd_idx = PGD_INDEX(va);
        uint32_t pte_idx = PTE_INDEX(va);

        pte_t *pte = (pte_t *)(pgd_now[pgd_idx] & PAGE_MASK);

        if (!pte) {
                return;
        }

        // 转换到内核线性地址
        pte = (pte_t *)(pa_to_ka(pte));

        pte[pte_idx] = 0;
        
        tlb_reload_page(va);
}

uint32_t get_mapping(pgd_t *pgd_now, uint32_t va, uint32_t *pa)
{
        uint32_t pgd_idx = PGD_INDEX(va);
        uint32_t pte_idx = PTE_INDEX(va);

        pte_t *pte = (pte_t *)(pgd_now[pgd_idx] & PAGE_MASK);
        if (!pte) {
              return 0;
        }
        
        // 转换到内核线性地址
        pte = (pte_t *)(pa_to_ka(pte));

        // 如果地址有效而且指针不为NULL,则返回地址
        if (pte[pte_idx] != 0 && pa) {
                 *pa = pte[pte_idx] & PAGE_MASK;
                return 1;
        }

        return 0;
}



================================================
FILE: arch/i386/mm/vmm.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  vmm.h
 *
 *    Description:  虚拟内存管理相关
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 11时41分59秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */
 
#ifndef INCLUDE_MM_VMM_H
#define INCLUDE_MM_VMM_H

#include <arch.h>
#include <types.h>
#include <lib/list.h>

/* *
 * Virtual memory map:
 *
 *
 *     4G ------------------> +---------------------------------+
 *                            |                                 |
 *                            |         Empty Memory (*)        |
 *                            |                                 |
 *                            +---------------------------------+ 0xF8000000
 *                            |                                 |
 *                            |                                 |
 *                            |    Remapped Physical Memory     | RW/-- KMEMSIZE
 *                            |                                 |
 *                            |                                 |
 *                            +---------------------------------+ 
 *                            |             Kernel              |
 *     KERNBASE ------------> +---------------------------------+ 0xC0000000
 *                            |        Invalid Memory (*)       | --/--
 *     USERTOP -------------> +---------------------------------+ 0xB0000000
 *                            |           User stack            |
 *                            +---------------------------------+
 *                            :                                 :
 *                            |         ~~~~~~~~~~~~~~~~        |
 *                            :                                 :
 *                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *                            |       User Program & Heap       |
 *     UTEXT ---------------> +---------------------------------+ 0x00800000
 *                            |        Invalid Memory (*)       | --/--
 *      USERBASE -----------> +---------------------------------+ 0x00200000
 *                            |        Invalid Memory (*)       | --/--
 *     0 -------------------> +---------------------------------+ 0x00000000
 * (*) Note: The kernel ensures that "Invalid Memory" is *never* mapped.
 *     "Empty Memory" is normally unmapped, but user programs may map pages
 *     there if desired.
 *
 * */

// A linear address 'la' has a three-part structure as follows:
//
// +--------10------+-------10-------+---------12----------+
// | Page Directory |   Page Table   | Offset within Page  |
// |      Index     |     Index      |                     |
// +----------------+----------------+---------------------+
//   \PGD_INDEX(la)/ \ PTE_INDEX(la) /  \OFFSET_INDEX(la)/

// 虚拟分页大小(4KB)
#define PAGE_SIZE 	  (0x1000)

// 页掩码,用于 4KB 对齐
#define PAGE_MASK         (0xFFFFF000)

// 内核起始虚拟地址
#define KERNBASE          (0xC0000000)

// 内核管理内存的大小
#define KMEMSIZE          (0x38000000)

// 内核页表大小
#define KVPAGE_SIZE       (0x400000)

// 内核管理的物理内存的顶端地址
#define KERNTOP           (KERNBASE + KMEMSIZE)

// 内核的偏移地址
#define PAGE_OFFSET 	  KERNBASE

// 每个页表可以映射的内存数
#define PAGE_MAP_SIZE 	  (0x400000)

// 映射 KMEM_SIZE 的内存所需要的页数
#define PTE_COUNT         (KMEMSIZE/PAGE_MAP_SIZE)

// 获取一个地址的页目录项
#define PGD_INDEX(x)      (((x) >> 22) & 0x3FF)

// 获取一个地址的页表项
#define PTE_INDEX(x)      (((x) >> 12) & 0x3FF)

// 获取一个地址的页內偏移
#define OFFSET_INDEX(x)   ((x) & 0xFFF)

// P--位0是存在标识,为 1 则内存页在内存中
#define PAGE_PRESENT 	(0x1)

// R/W--位1是读/写标识,如果等于 1,表示页面可以被读、写或执行。
#define PAGE_WRITE 	(0x2)

// U/S--位2是用户/超级用户标识,为 1 则任何特权级上的程序都可以访问该页面。
#define PAGE_USER 	(0x4)

// 页表成员数
#define PGD_SIZE (PAGE_SIZE/sizeof(pte_t))

// 页表成员数
#define PTE_SIZE (PAGE_SIZE/sizeof(uint32_t))

// 任务内存信息
struct mm_struct {
        pgd_t *pgdir;
        int vma_count;
        struct list_head vma_list;
};

// 任务虚拟内存区间
struct vma_struct {
        struct mm_struct *mm;
        uint32_t vm_start;
        uint32_t vm_end;
        uint32_t vm_flags;
        struct list_head list;
};

#define le_to_vma(le) list_entry(le, struct vma_struct, list)

#define VM_READ       (1u << 0)
#define VM_WRITE      (1u << 1)
#define VM_EXEC       (1u << 2)

// 物理地址转换内核虚拟地址
static inline void *pa_to_ka(void *pa)
{
        return (void *)((uint32_t)pa + KERNBASE);
}

// 内核虚拟地址转换物理地址
static inline void *ka_to_pa(void *ka)
{
        return (void *)((uint32_t)ka - KERNBASE);
}

// 内核页目录区域
extern pgd_t pgd_kern[];

// 虚拟内存管理初始化
void vmm_init(void);

// 使用 flags 指出的页权限,把物理地址 pa 映射到虚拟地址 va
void map(pgd_t *pgd_now, uint32_t va, uint32_t pa, uint32_t flags);

// 取消虚拟地址 va 的物理映射
void unmap(pgd_t *pgd_now, uint32_t va);

// 如果虚拟地址 va 映射到物理地址则返回 1
// 同时如果 pa 不是空指针则把物理地址写入 pa 参数
uint32_t get_mapping(pgd_t *pgd_now, uint32_t va, uint32_t *pa);

// 页错误中断的函数处理
void do_page_fault(pt_regs_t *regs);

#endif 	// INCLUDE_MM_VMM_H


================================================
FILE: arch/i386/syscall/syscall.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  syscall.c
 *
 *    Description:  系统调用相关
 *
 *        Version:  1.0
 *        Created:  2014年11月16日 12时19分36秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <types.h>
#include <debug.h>
#include <fs.h>
#include <intr/intr.h>

#include "syscall.h"

static int sys_test(uint32_t args[])
{
        int errno = (int)args[0];

        cprintk(rc_black, rc_light_brown, "\n\tsys_test run here!\n");

        return errno;
}

static int sys_exit(uint32_t args[])
{
        int errno = (int)args[0];

        return errno;
}

static int sys_fork(uint32_t args[])
{
        int errno = (int)args[0];

        return errno;
}

static int sys_read(uint32_t args[])
{
        int fd = (int)args[0];
        char *buff = (char *)args[1];
        size_t size = (size_t)args[2];

        return vfs_read(fd, buff, size);;
}

static int sys_write(uint32_t args[])
{
        int fd = (int)args[0];
        const char *buff = (const char *)args[1];
        size_t size = (size_t)args[2];

        return vfs_write(fd, buff, size);
}

static int sys_open(uint32_t args[])
{
        const char *filename = (const char *)args[0];
        uint32_t openflag = args[1];

        return vfs_open(filename, openflag);
}

static int sys_close(uint32_t args[])
{
        int fd = (int)args[0];

        return vfs_close(fd);
}

static int sys_getpid(uint32_t args[])
{
        int errno = (int)args[0];

        return errno;
}

// 系统调用函数指针数组
static int (*syscalls[])(uint32_t args[]) = {
        [SYS_test] = sys_test,
        [SYS_exit] = sys_exit,
        [SYS_fork] = sys_fork,
        [SYS_read] = sys_read,
        [SYS_write] = sys_write,
        [SYS_open] = sys_open,
        [SYS_close] = sys_close,
        [SYS_getpid] = sys_getpid
};

void syscall_handler(pt_regs_t *regs)
{
        uint32_t args[5];
        
        int sysno = regs->eax;
        if (sysno >= 0 && sysno <= SYSCALL_MAX) {
                if (syscalls[sysno]) {
                        // 系统调用寄存器传参规范
                        args[0] = regs->ebx;
                        args[1] = regs->ecx;
                        args[2] = regs->edx;
                        args[3] = regs->esi;
                        args[4] = regs->edi;
                        // 返回值由 eax 寄存器带回
                        regs->eax = syscalls[sysno](args);
                }
        }
}



================================================
FILE: arch/i386/syscall/syscall.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  syscall.h
 *
 *    Description:  系统调用相关
 *
 *        Version:  1.0
 *        Created:  2014年11月16日 12时17分43秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_SYSCALL_SYSCALL_H_
#define INCLUDE_SYSCALL_SYSCALL_H_

// 系统调用号
#define SYS_test      0
#define SYS_exit      1
#define SYS_fork      2
#define SYS_read      3
#define SYS_write     4
#define SYS_open      5
#define SYS_close     6
#define SYS_getpid    7

#define SYSCALL_MAX   7

// 系统调用函数
void syscall_handler(pt_regs_t *regs);

#endif  // INCLUDE_SYSCALL_SYSCALL_H_


================================================
FILE: arch/i386/task/entry.s
================================================
; -------------------------------------------------
;       内核创建线程的统一入口函数
;
;       qianyi.lh  2014/11/12  14:45:54
; -------------------------------------------------

[GLOBAL kthread_entry]
[EXTERN do_exit]

kthread_entry:
        push edx         ; push args
        call ebx         ; call fn
        push eax         ; push fn(args) return code
        call do_exit


================================================
FILE: arch/i386/task/switch_to.s
================================================
; -------------------------------------------------
; 	任务切换的实现
;
; 	qianyi.lh  2014/11/12  16:38:56
;
; -------------------------------------------------

[global switch_to]

switch_to:
        mov eax, [esp+4]
        
        push ebx
        mov ebx, [esp+4]
        mov [eax], ebx
        pop ebx
        
        mov [eax+4], esp
        mov [eax+8], ebp
        mov [eax+12], ecx
        mov [eax+16], edx
        mov [eax+20], esi
        mov [eax+24], edi
        mov [eax+28], ebp

        mov eax, [esp+8]

        mov ebp, [eax+28]
        mov edi, [eax+24]
        mov esi, [eax+20]
        mov edx, [eax+16]
        mov ecx, [eax+12]
        mov ebx, [eax+8]
        mov esp, [eax+4]
        
        push ebx
        push ebx
        mov ebx, [eax]
        mov [esp+4], ebx
        pop ebx
 	
        ret



================================================
FILE: arch/i386/task/task.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  task.c
 *
 *    Description:  任务相关的定义
 *
 *        Version:  1.0
 *        Created:  2014年11月12日 12时24分42秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <debug.h>
#include <sync.h>
#include <common.h>
#include <sched.h>
#include <mm/mm.h>
#include <lib/string.h>
#include <syscall/syscall.h>

#include "task.h"

struct list_head task_list;

struct task_struct *glb_idle_task;
struct task_struct *glb_init_task;

// 任务总数
static int nr_task = 0;

static uint32_t glb_pid_map[MAX_PID/32];

static pid_t alloc_pid(void)
{
        for (int i = 0; i < MAX_PID/32; ++i) {
                if (glb_pid_map[i] == 0xFFFFFFFF) {
                        continue;
                }
                for (int j = 0; j < 32; ++j) {
                        if (((1u << j) & glb_pid_map[i]) == 0) {
                                glb_pid_map[i] |= 1u << j;
                                return (pid_t)(i * 32 + j);
                        }
                }
        }

        return -1;
}

static void free_pid(pid_t pid)
{
        if (pid < 0 || pid > MAX_PID) {
                return;
        }
        glb_pid_map[pid/32] &= ~(1u << (pid % 32));
}

void task_init(void)
{
        INIT_LIST_HEAD(&task_list);
        struct task_struct *idle_task = (struct task_struct *)kern_stack;

        bzero(idle_task, sizeof(struct task_struct));

        idle_task->state = TASK_RUNNABLE;
        idle_task->stack = (void *)kern_stack_top;
        idle_task->pid = alloc_pid();
        idle_task->need_resched = true;
        set_proc_name(idle_task, "idle");

        nr_task++;
        list_add(&idle_task->list, &task_list);

        glb_idle_task = idle_task;

        // 注册系统调用中断
        register_interrupt_handler(0x80, syscall_handler);
}

// 声明创建的内核线程入口函数
extern int kthread_entry(void *args);

int kernel_thread(int (*func)(void *), void *args, uint32_t clone_flags)
{
        pt_regs_t pt_regs;
        bzero(&pt_regs, sizeof(pt_regs_t));

        pt_regs.cs = KERNEL_CS;
        pt_regs.ds = KERNEL_DS;
        pt_regs.ss = KERNEL_DS;
        pt_regs.ebx = (uint32_t)func;
        pt_regs.edx = (uint32_t)args;
        pt_regs.eip = (uint32_t)kthread_entry;

        return do_fork(clone_flags | CLONE_VM, &pt_regs);
}

// 切换函数
extern void switch_to(struct context *from, struct context *to);

void task_run(struct task_struct *task)
{
        if (task != current) {
                struct task_struct *prev = current;
                struct task_struct *next = task;
                bool intr_flag = false;
                local_intr_store(intr_flag);
                {
                	//tss_load_esp(uint32_t)next->stack);
                        if (!task && task->mm && task->mm->pgdir) {
                                // load cr3
                        }
                        switch_to(&prev->context, &next->context);
                }
                local_intr_restore(intr_flag);
        }
}

struct task_struct *get_current(void)
{
        register uint32_t esp __asm__ ("esp");;

        return (struct task_struct *)(esp & (~(STACK_SIZE-1)));
}

struct task_struct *find_task(pid_t pid)
{
        if (pid > 0 && pid < MAX_PID) {
                struct list_head *le;
                list_for_each(le, &task_list) {
                        struct task_struct *task = le_to_task(le);
                        if (task->pid == pid) {
                                return task;
                        }
                }
        }

        return NULL;
}

void set_proc_name(struct task_struct *task, char *name)
{
        bzero(task->name, sizeof(task->name));
        strncpy(task->name, name, TASK_NAME_MAX);
}

static struct task_struct *alloc_task_struct(void)
{
        void *addr = (void *)alloc_pages(STACK_SIZE/PAGE_SIZE);
        assert(addr != 0, "alloc_task_struct error!");

        struct task_struct *task = pa_to_ka(addr);
        bzero(task, sizeof(struct task_struct));

        task->state = TASK_UNINIT;
        task->stack = task_to_stack(task);
        task->pid = -1;

        return task;
}

static int copy_mm(uint32_t clone_flags, struct task_struct *task)
{
        if (!clone_flags && !task) {
                return -1;
        }

        return 0;
}

// 定义在 intr_s.s
void forkret_s(struct pt_regs_t *pt_regs);

static void copy_thread(struct task_struct *task, struct pt_regs_t *pt_regs)
{
        task->pt_regs = (struct pt_regs_t *)((uint32_t)task->stack - sizeof(struct pt_regs_t));
        *(task->pt_regs) = *pt_regs;
        task->pt_regs->eax = 0;
        task->pt_regs->esp = (uint32_t)task->stack;
        task->pt_regs->eflags |= FL_IF;

        task->context.eip = (uint32_t)forkret_s;
        task->context.esp = (uint32_t)task->pt_regs;
}

pid_t do_fork(uint32_t clone_flags, struct pt_regs_t *pt_regs)
{
        if (nr_task >= MAX_TASK) {
                return -E_NO_FREE_PROC;
        }

        struct task_struct *task = alloc_task_struct();
        if (!task) {
                return -E_NO_MEM;
        }

        if (copy_mm(clone_flags, task) != 0) {
                free_pages((uint32_t)ka_to_pa(task), STACK_SIZE/PAGE_SIZE);
                return -E_NO_MEM;
        }

        copy_thread(task, pt_regs);

        bool intr_flag = false;
        local_intr_store(intr_flag);
        {
                task->pid = alloc_pid();
                list_add(&task->list, &task_list);
                nr_task ++;
        }
        local_intr_restore(intr_flag);

        wakeup_task(task);

        return task->pid;
}

void do_exit(int errno)
{
        bool intr_flag = false;
        local_intr_store(intr_flag);
        {
                current->state = TASK_ZOMBIE;
                current->exit_code = errno;
                current->need_resched = true;
                nr_task--;
                free_pid(current->pid);
        }
        local_intr_restore(intr_flag);

        cpu_idle();
}

void cpu_idle(void)
{
        if (current->need_resched) {
                schedule();
        }
}
 


================================================
FILE: arch/i386/task/task.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  task.h
 *
 *    Description:  任务相关定义
 *
 *        Version:  1.0
 *        Created:  2014年11月12日 10时18分52秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_TASK_H_
#define INCLUDE_TASK_H_

#include <types.h>
#include <arch.h>
#include <common.h>
#include <mm/mm.h>
#include <lib/list.h>
#include <fs.h>

// fork flag
#define CLONE_VM            0x00000100  // set if VM shared between processes
#define CLONE_THREAD        0x00000200  // thread group

// 任务状态字段
typedef
enum task_state {
        TASK_UNINIT = 0,       // 任务未初始化
        TASK_SLEEPING = 1,     // 任务休眠中
        TASK_RUNNABLE = 2,     // 任务可执行(可能正在执行)
        TASK_ZOMBIE = 3,       // 任务已结束(等待回收)
} task_state_t;

// 按照 x86 规范保存被调用者需要保存的寄存器即可
struct context {
        uint32_t eip;
        uint32_t esp;
        uint32_t ebx;
        uint32_t ecx;
        uint32_t edx;
        uint32_t esi;
        uint32_t edi;
        uint32_t ebp;
};

#define TASK_NAME_MAX  (20)
#define MAX_TASK       (4096)
#define MAX_PID        (MAX_TASK*2)

// 任务描述 PCB
struct task_struct {

        task_state_t state;             // 任务状态

        void *stack;                    // 任务的内核栈指针
        
        pid_t pid;                      // 任务的PID
        char name[TASK_NAME_MAX+1];     // 任务名称

        uint32_t runs_time;             // 当前任务运行时间
        volatile bool need_resched;     // 是否需要被重新调度
        
        struct task_struct *parent;     // 父进程指针
        
        struct mm_struct *mm;           // 任务的内存信息
        struct pt_regs_t *pt_regs;      // 任务中断保存的寄存器信息
        struct context context;         // 任务切换上下文信息
        uint32_t flags;                 // 任务的一些标识
        uint32_t exit_code;             // 任务的退出代码

        struct file_struct files;       // 文件系统相关信息
        
        struct list_head list;          // 任务链表
};

#define le_to_task(le) list_entry(le, struct task_struct, list)

extern struct list_head task_list;

// idle 任务指针
extern struct task_struct *glb_idle_task;

// init 任务指针
extern struct task_struct *glb_init_task;

/*  
 * 因为pt_regs结构最后的部分实际上是CPU自动压栈,内核访问的。
 * 即中断产生后,CPU会自动压入这些寄存器,ss和sp仅在特权级发生变化时压入
 * (比如从用户态ring0到ring3,会压入用户态的ss和sp),
 * 如果是内核态发生中断,CPU不会压入ss和sp,这种情况,再访问ss和sp字段就越界了,
 * 所以预留了8字节。
 */
#define task_to_stack(task) ((void *)((uint32_t)task + STACK_SIZE - 8))

#define current get_current()

// 获得当前执行的任务指针
struct task_struct *get_current(void);

// 任务调度初始化
void task_init(void);

// 运行一个任务
void task_run(struct task_struct *task);

// 创建一个内核线程
int kernel_thread(int (*func)(void *), void *args, uint32_t clone_flags);

// 通过 PID 查找任务
struct task_struct *find_task(pid_t pid);

// 设置任务名称
void set_proc_name(struct task_struct *task, char *name);

void cpu_idle(void);

pid_t do_fork(uint32_t clone_flags, struct pt_regs_t *pt_regs);

void do_exit(int errno);

#endif  // INCLUDE_TASK_H_


================================================
FILE: arch/x64/TODO
================================================
TODO


================================================
FILE: driver/block_dev.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  block_dev.c
 *
 *    Description:  块设备相关
 *
 *        Version:  1.0
 *        Created:  2015年02月08日 10时12分00秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <debug.h>
#include <lib/string.h>
#include <block_dev.h>
#include <mbr.h>

// 全局块设备链表
block_dev_t *block_devs;

// 块设备初始化
void block_dev_init(void)
{
        cprintk(rc_black, rc_red, "Init IDE Driver ...\n");

        block_dev_t *ide_dev = &ide_main_dev;
        if (ide_dev->ops.init() == -1) {
                printk("Main IDE Device Not Found!\n");
                return;
        }

        add_block_dev(ide_dev);

        if (!ide_dev->ops.device_valid()) {
                printk("Main IDE Device Error!\n");
                return;
        }

        cprintk(rc_black, rc_red, "Found IDE Driver: %u (sectors)  Desc: %s\n",
                        ide_dev->ops.get_nr_block(), ide_dev->ops.get_desc());

        if (read_mbr_info(ide_dev) != 0) {
                printk("Read MBR Info Error!");
        }
}

// 内核注册块设备
int add_block_dev(block_dev_t *bdev)
{
        block_dev_t *p = block_devs;
        while (p) {
                if (strcmp(p->name, bdev->name) == 0) {
                        return -1;
                }
                p = p->next;
        }

        bdev->next = block_devs;
        block_devs = bdev;

        return 0;
}


================================================
FILE: driver/char_dev.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  char_dev.c
 *
 *    Description:  字符设备相关
 *
 *        Version:  1.0
 *        Created:  2015年02月08日 10时13分36秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <debug.h>
#include <char_dev.h>
#include <lib/string.h>

// 全局字符设备链表
char_dev_t *char_devs;

// 字符设备初始化
void char_dev_init(void)
{
        char_dev_t *kb_dev = &kboard_dev;
        kb_dev->ops.init();
        add_char_dev(kb_dev);

        cprintk(rc_black, rc_magenta, "Init %s device ...\n\n", kb_dev->ops.get_desc());
}

// 内核注册字符设备
int add_char_dev(char_dev_t *cdev)
{
        char_dev_t *p = char_devs;
        while (p) {
                if (strcmp(p->name, cdev->name) == 0) {
                        return -1;
                }
                p = p->next;
        }

        cdev->next = char_devs;
        char_devs = cdev;

        return 0;
}



================================================
FILE: driver/device.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  device.c
 *
 *    Description:  外部设备相关
 *
 *        Version:  1.0
 *        Created:  2015年02月08日 11时47分59秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <device.h>
#include <char_dev.h>
#include <block_dev.h>

// 外部设备初始化
void device_init(void)
{
        char_dev_init();
        block_dev_init();
}




================================================
FILE: driver/ide.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  ide.c
 *
 *    Description:  IDE 设备驱动
 *
 *        Version:  1.0
 *        Created:  2015年02月03日 14时55分53秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <types.h>
#include <common.h>
#include <debug.h>

#include <block_dev.h>

#define SECTSIZE  512 // 默认扇区大小

/** 
 * bit 7 = 1  控制器忙         * bit 6 = 1  驱动器就绪
 * bit 5 = 1  设备错误         * bit 4      N/A
 * bit 3 = 1  扇区缓冲区错误   * bit 2 = 1  磁盘已被读校验
 * bit 1        N/A            * bit 0 = 1  上一次命令执行失败
 */
#define IDE_BSY                 0x80            // IDE驱动器忙 
#define IDE_DRDY                0x40            // IDE驱动器就绪
#define IDE_DF                  0x20            // IDE驱动器错误
#define IDE_ERR                 0x01            // 上一次命令失败

#define IDE_CMD_READ            0x20            // IDE读扇区命令
#define IDE_CMD_WRITE           0x30            // IDE写扇区命令
#define IDE_CMD_IDENTIFY        0xEC            // IDE识别命令

// IDE设备端口起始端口定义
#define IOBASE                  0x1F0             // 主IDE设备起始操作端口
#define IOCTRL                  0x3F4             // 主IDE控制起始控制端口

// IDE设备控制端口偏移量
#define ISA_DATA                0x00            // IDE数据端口偏移
#define ISA_ERROR               0x01            // IDE错误端口偏移
#define ISA_PRECOMP             0x01            
#define ISA_CTRL                0x02            // IDE控制端口偏移
#define ISA_SECCNT              0x02
#define ISA_SECTOR              0x03
#define ISA_CYL_LO              0x04
#define ISA_CYL_HI              0x05
#define ISA_SDH                 0x06            // IDE选择端口偏移
#define ISA_COMMAND             0x07            // IDE命令端口偏移
#define ISA_STATUS              0x07            // IDE状态端口偏移

// IDE设备限制值
#define MAX_NSECS               128             // IDE设备最大操作扇区数
#define MAX_DISK_NSECS          0x10000000      // IDE设备最大扇区号

// IDE设备身份信息在读取的信息块中的偏移
#define IDE_IDENT_SECTORS       20
#define IDE_IDENT_MODEL         54
#define IDE_IDENT_CAPABILITIES  98
#define IDE_IDENT_CMDSETS       164
#define IDE_IDENT_MAX_LBA       120
#define IDE_IDENT_MAX_LBA_EXT   200

#define IDE_DESC_LEN            40              // IDE设备描述信息尺寸

// IDE设备信息
static struct ide_device {
        uint8_t valid;                   // 是否可用
        uint32_t sets;                   // 命令支持
        uint32_t size;                   // 扇区数量
        char desc[IDE_DESC_LEN+1];       // IDE设备描述
} ide_device;

// 初始化IDE设备
static int ide_init(void);

// 检测IDE设备是否可用
static bool ide_device_valid(void);

// 获取IDE设备描述
static const char *ide_get_desc(void);

// 获得设备默认块数量
static int ide_get_nr_block(void);

// 设备操作请求
static int ide_request(io_request_t *req);

// 读取IDE设备若干扇区
static int ide_read_secs(uint32_t secno, void *dst, uint32_t nsecs);

// 写入IDE设备若干扇区
static int ide_write_secs(uint32_t secno, const void *src, uint32_t nsecs);

// IDE设备选项设置
static int ide_ioctl(int op, int flag);

// IDE 设备结构
block_dev_t ide_main_dev = {
        .name = "IDE_MAIN",
        .block_size = SECTSIZE,
        .ops = {
                .init = &ide_init,
                .device_valid = &ide_device_valid,
                .get_desc = &ide_get_desc,
                .get_nr_block = &ide_get_nr_block,
                .request = &ide_request,
                .ioctl = ide_ioctl
        }
};

// 等待IDE设备可用
static int32_t ide_wait_ready(uint16_t iobase, bool check_error)
{
        int r = 0;
        while ((r = inb(iobase + ISA_STATUS)) & IDE_BSY) {
                // Waiting ... Do nothing ...
        }
        if (check_error && (r & (IDE_DF | IDE_ERR)) != 0) {
                return -1;
        }

        return 0;
}

// 获取IDE设备描述
static const char *ide_get_desc(void)
{
        return (const char *)(ide_device.desc);
}

// 初始化IDE设备
static int ide_init(void)
{
        ide_wait_ready(IOBASE, 0);

        // 1: 选择要操作的设备
        outb(IOBASE + ISA_SDH, 0xE0);
        ide_wait_ready(IOBASE, 0);

        // 2: 发送IDE信息获取命令
        outb(IOBASE + ISA_COMMAND, IDE_CMD_IDENTIFY);
        ide_wait_ready(IOBASE, 0);

        // 3: 检查设备是否存在
        if (inb(IOBASE + ISA_STATUS) == 0 || ide_wait_ready(IOBASE, 1) != 0) {
                return -1;
        }

        ide_device.valid = 1;

        // 读取IDE设备信息
        uint32_t buffer[128];
        insl(IOBASE + ISA_DATA, buffer, sizeof(buffer) / sizeof(uint32_t));

        uint8_t *ident = (uint8_t *)buffer;
        uint32_t cmdsets = *(uint32_t *)(ident + IDE_IDENT_CMDSETS);
        uint32_t sectors;

        // 检查设备使用48-bits还是28-bits地址
        if (cmdsets & (1 << 26)) {
                sectors = *(uint32_t *)(ident + IDE_IDENT_MAX_LBA_EXT);
        }
        else {
                sectors = *(uint32_t *)(ident + IDE_IDENT_MAX_LBA);
        }
        ide_device.sets = cmdsets;
        ide_device.size = sectors;

        char *desc = ide_device.desc;
        char *data = (char *)((uint32_t)ident + IDE_IDENT_MODEL);

        // 复制设备描述信息
        int i, length = IDE_DESC_LEN;
        for (i = 0; i < length; i += 2) {
                desc[i] = data[i+1];
                desc[i+1] = data[i];
        }
        do {
                desc[i] = '\0';
        } while (i-- > 0 && desc[i] == ' ');

        return 0;
}

// 检测指定IDE设备是否可用
static bool ide_device_valid(void)
{
        return ide_device.valid == 1;
}

// 获得设备默认块数量
static int ide_get_nr_block(void)
{
        if (ide_device_valid()) {
                return ide_device.size;
        }

        return 0;
}

// 设备操作请求
static int ide_request(io_request_t *req)
{
        if (req->io_type == IO_READ) {
                if (req->bsize < SECTSIZE * req->nsecs) {
                        return -1;
                }
                return ide_read_secs(req->secno, req->buffer ,req->nsecs);
        } else if (req->io_type == IO_WRITE) {
                if (req->bsize < SECTSIZE * req->nsecs) {
                        return -1;
                }
                return ide_write_secs(req->secno, req->buffer ,req->nsecs);
        }

        return -1;
}

// 读取指定IDE设备若干扇区
static int ide_read_secs(uint32_t secno, void *dst, uint32_t nsecs)
{
        assert(nsecs <= MAX_NSECS && ide_device.valid == 1, "nsecs or ide error!");
        assert(secno < MAX_DISK_NSECS && secno + nsecs <= MAX_DISK_NSECS, "secno error!");

        ide_wait_ready(IOBASE, 0);

        outb(IOCTRL + ISA_CTRL, 0);
        outb(IOBASE + ISA_SECCNT, nsecs);
        outb(IOBASE + ISA_SECTOR, secno & 0xFF);
        outb(IOBASE + ISA_CYL_LO, (secno >> 8) & 0xFF);
        outb(IOBASE + ISA_CYL_HI, (secno >> 16) & 0xFF);
        outb(IOBASE + ISA_SDH, 0xE0 | ((secno >> 24) & 0xF));
        outb(IOBASE + ISA_COMMAND, IDE_CMD_READ);

        int ret = 0;
        for ( ; nsecs > 0; nsecs --, dst += SECTSIZE) {
                if ((ret = ide_wait_ready(IOBASE, 1)) != 0) {
                        return ret;
                }
                insl(IOBASE, dst, SECTSIZE / sizeof(uint32_t));
        }

        return ret;
}

// 写入指定IDE设备若干扇区
static int ide_write_secs(uint32_t secno, const void *src, uint32_t nsecs)
{
        assert(nsecs <= MAX_NSECS && ide_device.valid == 1, "nsecs or ide error");
        assert(secno < MAX_DISK_NSECS && secno + nsecs <= MAX_DISK_NSECS, "secno error!");

        ide_wait_ready(IOBASE, 0);

        outb(IOCTRL + ISA_CTRL, 0);
        outb(IOBASE + ISA_SECCNT, nsecs);
        outb(IOBASE + ISA_SECTOR, secno & 0xFF);
        outb(IOBASE + ISA_CYL_LO, (secno >> 8) & 0xFF);
        outb(IOBASE + ISA_CYL_HI, (secno >> 16) & 0xFF);
        outb(IOBASE + ISA_SDH, 0xE0 | ((secno >> 24) & 0xF));
        outb(IOBASE + ISA_COMMAND, IDE_CMD_WRITE);

        int ret = 0;
        for ( ; nsecs > 0; nsecs --, src += SECTSIZE) {
                if ((ret = ide_wait_ready(IOBASE, 1)) != 0) {
                        return ret;
                }
                outsl(IOBASE, src, SECTSIZE / sizeof(uint32_t));
        }

        return ret;
}

// IDE设备选项设置
static int ide_ioctl(int op, int flag)
{
        if (op != 0 && flag != 0) {
                return -1;
        }

        return 0;
}



================================================
FILE: driver/kboard.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  kboard.c
 *
 *    Description:  键盘驱动
 *
 *        Version:  1.0
 *        Created:  2015年02月05日 13时33分22秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <common.h>
#include <intr/intr.h>

#include <char_dev.h>

/*
 * 键盘当前状态信息(相关位被设置即为有效)
 *
 * 0: control
 * 1: alt
 * 2: alt-gr
 * 3: left shift
 * 4: right shift
 * 5: caps_lock
 * 6: scroll_lock
 * 7: num_lock
 */
#define CONTROL         0x1
#define ALT             0x2
#define ALTGR           0x4
#define LSHIFT          0x8
#define RSHIFT          0x10
#define CAPSLOCK        0x20
#define SCROLLLOCK      0x40
#define NUMLOCK         0x80

// 8 位的键盘扫描码的接通码使用前7位
// 其最高位置 1 即是其对应的断开码
// 该宏可以和获取的扫描码用来判断一个键是按下还是抬起
#define RELEASED_MASK 0x80

typedef uint8_t key_status_t;

typedef
struct keymap {
        uint8_t scancodes[128];         // 键盘扫描码的映射
        uint8_t capslock_scancodes[128];
        uint8_t shift_scancodes[128];
        uint8_t control_map[8];
        key_status_t controls;          // 键盘的控制状态信息
} keymap_t;

static keymap_t us_keymap = {
        //normal keys
        {
                /* first row - indices 0 to 14 */
                0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',
                /* second row - indices 15 to 28 */
                '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', //Enter key
                /* 29 = Control, 30 - 41: third row */
                0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
                /* fourth row, indices 42 to 54, zeroes are shift-keys*/
                0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0,
                '*',
                /* Special keys */
                0,    // ALT - 56
                ' ', // Space - 57
                0,    // Caps lock - 58
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F1 to F10 - 59 to 68
                0, // Num lock - 69
                0, // Scroll lock - 70
                0, // Home - 71
                72, // Up arrow - 72  TODO
                0, // Page up - 73
                '-',
                0, // Left arrow - 75
                0,
                0, // Right arrow -77
                '+',
                0, // End - 79
                80, // Dowm arrow - 80  TODO
                0, // Page down - 81
                0, // Insert - 82
                0, // Delete - 83
                0, 0, 0,
                0, // F11 - 87
                0, // F12 - 88
                0, // All others undefined
        },
        // caps
        {
                /* first row - indices 0 to 14 */
                0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',
                /* second row - indices 15 to 28 */
                '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n',
                /* 29 = Control, 30 - 41: third row */
                0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', '\'', '`',
                /* fourth row, indices 42 to 54, zeroes are shift-keys*/
                0, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', ',', '.', '/', 0, '*',
                /* Special keys */
                0,   // ALT - 56
                ' ', // Space - 57
                0,   // Caps lock - 58
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F1 to F10 - 59 to 68
                0, // Num lock - 69
                0, // Scroll lock - 70
                0, // Home - 71
                0, // Up arrow - 72
                0, // Page up - 73
                '-',
                0, // Left arrow - 75
                0,
                0, // Right arrow -77
                '+',
                0, // End - 79
                0, // Dowm arrow - 80
                0, // Page down - 81
                0, // Insert - 82
                0, // Delete - 83
                0, 0, 0,
                0, // F11 - 87
                0, // F12 - 88
                0, // All others undefined
        },
        // shift
        {
                /* first row - indices 0 to 14 */
                0, 27, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b',
                /* second row - indices 15 to 28 */
                '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n',
                /* 29 = Control, 30 - 41: third row */
                0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',
                /* fourth row, indices 42 to 54, zeroes are shift-keys*/
                0, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0, '*',
                /* Special keys */
                0,   // ALT - 56
                ' ', // Space - 57
                0,   // Caps lock - 58
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F1 to F10 - 59 to 68
                0, // Num lock - 69
                0, // Scroll lock - 70
                0, // Home - 71
                0, // Up arrow - 72
                0, // Page up - 73
                '-',
                0, // Left arrow - 75
                0,
                0, // Right arrow -77
                '+',
                0, // End - 79
                0, // Dowm arrow - 80
                0, // Page down - 81
                0, // Insert - 82
                0, // Delete - 83
                0, 0, 0,
                0, // F11 - 87
                0, // F12 - 88
                0, // All others undefined
        },
        // control_map
        {
                29, // Ctrl
                56, // Alt
                0,  // AltGr
                42, // left Shift
                54, // right Shift
                58, // Caps lock
                70, // Scroll lock
                69  // Num lock
        },
        // 键盘的控制键信息初始化为 0 
        0
};

// 设备初始化
static int kb_init(void);

// 设备是否可用
static bool kb_device_valid(void);

// 获取设备描述
static const char *kb_get_desc(void);

// 设备读取
static int kb_read(void *dec, uint32_t len);

// 设备写入
static int kb_write(const void *src, uint32_t len);

// 设备控制
static int kb_ioctl(int op, int flag);

// 键盘中断处理函数
static void keyboard_handler(__UNUSED__ pt_regs_t *regs);

// Keyboard 设备结构
char_dev_t kboard_dev = {
        .name = "Keyboard",
        .is_readable = true,
        .is_writeable = false,
        .ops = {
                .init = kb_init,
                .device_valid = kb_device_valid,
                .get_desc = kb_get_desc,
                .read = kb_read,
                .write = kb_write,
                .ioctl = kb_ioctl
        }
};

#define KBUFFER_LEN     1024

// Keyboard 管理信息
static struct kboard_device {
        bool is_valid;                   // 设备是否可用
        keymap_t *curr_layout;           // 当前的字符集
        uint8_t kbuffer[KBUFFER_LEN];    // 键盘输入的缓冲区队列
        uint32_t kfront;                 // 缓冲队列队头
        uint32_t krear;                  // 缓冲队列队尾
} kb_device;

// 设备初始化
static int kb_init(void)
{
        // 采用US字符集
        kb_device.curr_layout = &us_keymap;

        // 设置设备可用
        kb_device.is_valid = true;

        // 注册键盘中断处理函数
        register_interrupt_handler(IRQ1, &keyboard_handler);

        return 0;
}

// 设备是否可用
static bool kb_device_valid(void)
{
        return kb_device.is_valid;
}

// 获取设备描述
static const char *kb_get_desc(void)
{
        return "Keyboard";
}

static uint8_t kb_getchar(void)
{
        // 队列中有数据则取出,否则返回 0
        if (kb_device.kfront != kb_device.krear) {
                char ch = kb_device.kbuffer[kb_device.kfront];
                kb_device.kfront = (kb_device.kfront + 1) % KBUFFER_LEN;
                return ch;
        } else {
                return 0;
        }
}

// 设备读取
static int kb_read(void *dec, uint32_t len)
{
        uint8_t *buffer = (uint8_t *)dec;
        uint8_t ch = 0;
        uint32_t i = 0;
        while (i < len) {
                if ((ch = kb_getchar()) != 0) {
                        buffer[i] = ch;
                        i++;
                } else {
                        break;
                }
        }

        return i;
}

// 设备写入
static int kb_write(__UNUSED__ const void *src, __UNUSED__ uint32_t len)
{
        return -1;
}

// 键盘中断处理函数
static void keyboard_handler(__UNUSED__ pt_regs_t *regs)
{
        // 从键盘端口读入按下的键
        uint8_t scancode = inb(0x60);

        keymap_t *layout = kb_device.curr_layout;

        // 首先判断是按下还是抬起
        if (scancode & RELEASED_MASK) {
                uint32_t i;
                // 我们只检查前 5 个控制键,因为前五位 Ctrl Alt Shift 松开后不保留状态
                // 所以这些按键松开后必须清除按下标记
                for (i = 0; i < 5; i++) {
                        if(layout->control_map[i] == (scancode & ~RELEASED_MASK)) {
                                layout->controls &= ~(1 << i);
                                return;
                        }
                }
        // 当键被按下
        } else {
                uint32_t i;
                // 逐一检查各个控制位
                for (i = 0; i < 8; i++) {
                        // 如果当前键是控制键,则给相关控制位置 1
                        // 如果已有该标志位,则给相关控制位清 0
                        if (layout->control_map[i] == scancode) {
                                if (layout->controls & 1 << i) {
                                      layout->controls &= ~(1 << i);
                                } else {
                                      layout->controls |= (1 << i);
                                }
                                return;
                        }
                }
                uint8_t *scancodes = layout->scancodes;
        
                // 如果此时按下了 shift 键,切换到 shift 扫描码
                if ((layout->controls & (LSHIFT | RSHIFT)) && !(layout->controls & CONTROL)) {
                      scancodes = layout->shift_scancodes;
                }
                // 如果此时处于大写锁定状态,切换到大写锁定的扫描码
                if ((layout->controls & (CAPSLOCK)) && !(layout->controls & CONTROL)) {
                      scancodes = layout->capslock_scancodes;
                }
                // 如果队列不满则字符入队,否则丢弃
                if (kb_device.kfront != (kb_device.krear + 1) % KBUFFER_LEN) {
                        kb_device.kbuffer[kb_device.krear] = scancodes[scancode];
                        kb_device.krear = (kb_device.krear + 1) % KBUFFER_LEN;
                }
        }
}


// 设备控制
static int kb_ioctl(int op, int flag)
{
        if (op != 0 && flag != 0) {
                return -1;
        }

        return 0;
}



================================================
FILE: fs/fs.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  fs.c
 *
 *    Description:  文件系统相关
 *
 *        Version:  1.0
 *        Created:  2015年02月08日 10时07分54秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <fs.h>
#include <device.h>

// vfs 初始化
void vfs_init(void);

// sfs 文件系统初始化
void sfs_init(void);

// 文件系统初始化
void fs_init(void)
{
        vfs_init();
        device_init();
        sfs_init();
}


================================================
FILE: fs/mbr.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  mbr.c
 *
 *    Description:  MBR 相关
 *
 *        Version:  1.0
 *        Created:  2015年02月08日 11时07分54秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <mbr.h>
#include <debug.h>

 // MBR信息
mbr_info_t mbr_info;

// 读取分区信息
int read_mbr_info(block_dev_t *bdev)
{
        io_request_t request;

        request.io_type = IO_READ;
        request.secno = 0;
        request.nsecs = 1;
        request.buffer = &mbr_info;
        request.bsize = sizeof(mbr_info);

        if (bdev->ops.request(&request) == 0) {
                return 0;
        }

        return -1;
}

void show_partition_info(void)
{
        cprintk(rc_black, rc_red, "\nPartition Info:\n");
        for (int i = 0; i < PARTITION_COUNT; ++i) {
                if (mbr_info.part[i].partition_type != 0) {
                        cprintk(rc_black, rc_red, "Active: %02X  ", mbr_info.part[i].active_flag);
                        cprintk(rc_black, rc_red, "Type: %02X  ", mbr_info.part[i].partition_type);
                        cprintk(rc_black, rc_red, "SCHS: %02X%02X%02X  ",  mbr_info.part[i].start_chs[0],
                                        mbr_info.part[i].start_chs[1], mbr_info.part[i].start_chs[2]);
                        cprintk(rc_black, rc_red, "ECHS: %02X%02X%02X  ", mbr_info.part[i].end_chs[0],
                                        mbr_info.part[i].end_chs[1], mbr_info.part[i].end_chs[2]);
                        cprintk(rc_black, rc_red, "Start: %04u  ", mbr_info.part[i].start_sector);
                        cprintk(rc_black, rc_red, "Count: %05u\n", mbr_info.part[i].nr_sectors);  
                }
        }
}


================================================
FILE: fs/ramfs/ramfs.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  ramfs.c
 *
 *    Description:  根文件系统
 *
 *        Version:  1.0
 *        Created:  2015年02月10日 12时06分50秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <fs.h>

// 读取super_block
static struct super_block *ramfs_read_super(struct super_block *sb);

// ramfs 定义
struct filesystem fs_ramfs = {
        .name = "ramfs",
        .type = RAMFS_T,
        .read_super = ramfs_read_super
};

// 申请 inode
static struct inode *ramfs_alloc_inode(struct super_block *sb);

// 释放inode
static void ramfs_destroy_inode(struct inode *inode);

// 设备写回超级块
static void ramfs_write_super(struct super_block *sb);

// 同步文件系统修改
static int ramfs_sync_fs(struct super_block *sb);

// super_block_ops 定义
static struct super_block_ops ramfs_sb_ops = {
        .alloc_inode = ramfs_alloc_inode,
        .destroy_inode = ramfs_destroy_inode,
        .write_super = ramfs_write_super,
        .sync_fs = ramfs_sync_fs,
};

// 读取super_block
static struct super_block *ramfs_read_super(struct super_block *sb)
{
        sb->s_type = RAMFS_T;
        sb->s_ops = &ramfs_sb_ops;

        return sb;
}

// 申请 inode
static struct inode *ramfs_alloc_inode(__UNUSED__ struct super_block *sb)
{
        return alloc_inode();
}

// 释放inode
static void ramfs_destroy_inode(struct inode *inode)
{
        free_inode(inode);
}

// 设备写回超级块
static void ramfs_write_super(__UNUSED__ struct super_block *sb)
{
        // do nothing ...
}

// 同步文件系统修改
static int ramfs_sync_fs(__UNUSED__ struct super_block *sb)
{
        // do nothing ...
        return 0;
}



================================================
FILE: fs/sfs/sfs.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  sfs.c
 *
 *    Description:  simple file system
 *
 *        Version:  1.0
 *        Created:  2015年02月10日 14时09分46秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <fs/sfs/sfs.h>
#include <debug.h>
#include <lib/string.h>
#include <lib/list.h>
#include <atomic.h>
#include <mbr.h>
#include <fs.h>

#define SUPER_BLOCK_OFFSET   4   // super_block 偏移
#define INODEMAP_OFFSET     12   // inode_map 偏移

// block 默认大小
#define BLOCK_SIZE        2048

// 最大文件大小
#define MAX_FILE_SIZE     (P_BLOCK_MAP_SIZE * BLOCK_SIZE + \
                         PP_BLOCK_MAP_SIZE * (BLOCK_SIZE / sizeof(uint32_t)) * BLOCK_SIZE)

// SFS 文件系统的 super_block
static struct super_block *sfs_sb;

// SFS 文件系统的 inode_map
static uint8_t *sfs_inode_map;

// SFS 文件系统的 block_map
static uint8_t *sfs_block_map;

// SFS 文件系统的 inode cache
static uint8_t **inode_cache;

// SFS 文件系统的 block cache
static uint8_t **block_cache;

// 初始化文件系统
static void sfs_mkfs(uint32_t start_sec, uint32_t end_sec, uint32_t block_size);

// 读取super_block
static struct super_block *sfs_read_super(struct super_block *sb);

// 回写 super_block
static void sfs_write_super(struct sfs_super_block *sb);

// 读取 inode_map
static int sfs_read_inode_map(void);

// 回写 inode_map
static void sfs_write_inode_map(void);

// 读取 block_map
static int sfs_read_block_map(void);

// 回写 block_map
static void sfs_write_block_map(void);

// 申请 inode 号
static uint32_t sfs_alloc_inode(void);

// 释放 inode 号
static void sfs_free_inode(uint32_t inode_no);

// 申请 block 号
static uint32_t sfs_alloc_block(void);

// 释放 block 号
static void sfs_free_block(uint32_t block_no);

// 读取 inode
// static struct sfs_inode *sfs_read_inode(uint32_t inode_no);

// 获取 inode 数据指针(从 inode_cache 获取,可能阻塞于磁盘IO)
static uint8_t *sfs_read_inode(uint32_t inode_no);

// 获取 blcok 指针(从 block_cache 获取,可能阻塞于磁盘IO)
static uint8_t *sfs_read_block(uint32_t block_no);

// sfs 定义
struct filesystem fs_sfs = {
        .name = "sfs",
        .type = SFS_T,
        .read_super = sfs_read_super
};

// sfs 文件系统初始化
void sfs_init(void)
{
        cprintk(rc_black, rc_cyan, "\nInit SFS Filesystem ...\n");

        if (add_filesystem(&fs_sfs) == -1) {
                printk("Add SFS Filesystem Error!\n");
        }

        uint32_t start_sec = 0;
        uint32_t end_sec = 0;
        for (int i = 0; i < PARTITION_COUNT; ++i) {
                if (mbr_info.part[i].partition_type == SFS_T) {
                        cprintk(rc_black, rc_cyan, "Found SFS Filesystem Partition:  ");
                        cprintk(rc_black, rc_cyan, "Start: %u Count: %u\n\n",
                                        mbr_info.part[i].start_sector, mbr_info.part[i].nr_sectors);
                        start_sec = mbr_info.part[i].start_sector;
                        end_sec = mbr_info.part[i].nr_sectors;
                }
        }
        if (start_sec > 0 && end_sec > 0 && end_sec > start_sec) {
                sfs_mkfs(start_sec, end_sec, BLOCK_SIZE);
        }
}

// 初始化文件系统
static void sfs_mkfs(uint32_t start_sec, uint32_t end_sec, uint32_t block_size)
{
        uint32_t sb_start = start_sec + SUPER_BLOCK_OFFSET;          // super_block 起始扇区
        uint32_t all_sec = end_sec - start_sec - INODEMAP_OFFSET;    // 可用扇区数

        // inode : block = 1 : 9
        uint32_t in_secs = all_sec / 10;                   // inode 所占扇区数
        uint32_t bl_secs = all_sec / 10 * 9;               // block 所占扇区数
        uint32_t in_count = in_secs;                       // inode 数量
        uint32_t bl_count = bl_secs / (block_size / 512);  // block 数量
        uint32_t im_start = start_sec + INODEMAP_OFFSET;   // inode map 起始
        uint32_t im_secs  = in_secs / 512 + 1;             // inode map 所占扇区数
        uint32_t bm_start = im_start + im_secs;            // block map 起始地址
        uint32_t bm_secs  = bl_secs / block_size + 1;      // block map 所占扇区数
        uint32_t in_start = bm_start + bm_secs;            // inode 起始位置
        uint32_t bl_start = in_start + in_secs;            // block 起始位置

        printk("super_block start: %u\n", sb_start);
        printk("all          secs: %u\n\n", all_sec);
        printk("inode_map   start: %u\n", im_start);
        printk("inode_map    secs: %u\n\n", im_secs);
        printk("block_map   start: %u\n", bm_start);
        printk("block_map    secs: %u\n\n", bm_secs);
        printk("inode       start: %u\n", in_start);
        printk("inode        secs: %u\n", in_secs);
        printk("inode       count: %u\n\n", in_count);
        printk("block       start: %u\n", bl_start);
        printk("block        secs: %u\n", bl_secs);
        printk("block       count: %u\n\n", bl_count);
        printk("max file size: %u B ~= %d MB\n\n", MAX_FILE_SIZE, MAX_FILE_SIZE / 1024 / 1024);

        struct sfs_super_block sfs_sb;
        bzero(&sfs_sb, sizeof(sfs_sb));

        sfs_sb.s_type = SFS_T;
        sfs_sb.s_inode_count = in_count;
        sfs_sb.s_block_count = bl_count;
        sfs_sb.s_block_size = block_size;
        sfs_sb.s_max_file = MAX_FILE_SIZE;
        sfs_sb.s_root_inode = 0;

        sfs_sb.in_secs = in_secs;
        sfs_sb.bl_secs = bl_secs;
        sfs_sb.im_start = im_start;
        sfs_sb.im_secs = im_secs;
        sfs_sb.bm_start = bm_start;
        sfs_sb.bm_secs = bm_secs;
        sfs_sb.in_start = in_start;
        sfs_sb.bl_start = bl_start;
}

// 读取super_block
static struct super_block *sfs_read_super(struct super_block *sb)
{
        sfs_sb = NULL;

        return NULL;
}

// 回写 super_block
static void sfs_write_super(struct sfs_super_block *sb)
{
}

// 读取 inode_map
static int sfs_read_inode_map(void)
{
        sfs_inode_map = NULL;

        return 0;
}

// 回写 inode_map
static void sfs_write_inode_map(void)
{
}

// 读取 block_map
static int sfs_read_block_map(void)
{
        sfs_block_map = NULL;
        return 0;
}

// 回写 block_map
static void sfs_write_block_map(void)
{
}

// 申请 inode 号
static uint32_t sfs_alloc_inode(void)
{
        return 0;
}

// 释放 inode 号
static void sfs_free_inode(uint32_t inode_no)
{
}

// 申请 block 号
static uint32_t sfs_alloc_block(void)
{
        return 0;
}

// 释放 block 号
static void sfs_free_block(uint32_t block_no)
{
}

// 获取 inode 数据指针(从 inode_cache 获取,可能阻塞于磁盘IO)
static uint8_t *sfs_read_inode(uint32_t inode_no)
{
        return NULL;
}


// 获取 blcok 指针(从 block_cache 获取,可能阻塞)
static uint8_t *sfs_read_block(uint32_t block_no)
{
        return NULL;
}



================================================
FILE: fs/sfs/sfs.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  sfs.h
 *
 *    Description:  simple file system
 *
 *        Version:  1.0
 *        Created:  2015年06月02日 10时09分46秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef FS_SFS_SFS_H
#define FS_SFS_SFS_H

#include <types.h>

struct sfs_super_block {
        uint16_t s_type;                // 文件系统类型
        uint32_t s_inode_count;         // inode数量
        uint32_t s_block_count;         // block数量
        uint32_t s_block_size;          // block大小
        uint32_t s_max_file;            // 文件最大尺寸
        uint32_t s_root_inode;          // 根目录 inode 号

        uint32_t in_secs;               // inode 所占扇区数
        uint32_t bl_secs;               // block 所占扇区数
        uint32_t im_start;              // inode map 起始
        uint32_t im_secs;               // inode map 所占扇区数
        uint32_t bm_start;              // block map 起始地址
        uint32_t bm_secs;               // block map 所占扇区数
        uint32_t in_start;              // inode 起始位置
        uint32_t bl_start;              // block 起始位置
};

#define P_BLOCK_MAP_SIZE     32            // 一级 block 数量
#define PP_BLOCK_MAP_SIZE    32            // 二级 block 数量

struct sfs_inode {
        uint32_t i_type;                // inode 类型
        uint32_t i_ino;                 // 索引节点号
        time_t i_atime;                 // 文件最后一次访问时间
        time_t i_mtime;                 // 文件最后一次修改时间
        time_t i_ctime;                 // 文件首次创建时间
        uint32_t i_size;                // 文件字节数
        uint32_t i_blocks;              // 文件使用block数
        uint32_t i_bytes;               // 文件最后一个block的字节数

        uint32_t p_block_map[P_BLOCK_MAP_SIZE];          // 一级 block 指向
        uint32_t pp_block_map[PP_BLOCK_MAP_SIZE];        // 二级 block 指向
};

// 最长文件名
#define SFS_MAX_FILE_NAME   123

// 目录类型inode存储的目录数据块 sizeof = 128
struct sfs_dirent {
        char d_name[SFS_MAX_FILE_NAME+1];   // 目录项名称
        uint32_t inode;                     // 对应的 inode 号
};

#endif  // FS_SFS_SFS_H


================================================
FILE: fs/vfs.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  vfs.c
 *
 *    Description:  虚拟文件系统
 *
 *        Version:  1.0
 *        Created:  2015年02月06日 10时15分38秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <debug.h>
#include <atomic.h>
#include <arch.h>
#include <mm/mm.h>
#include <lib/string.h>
#include <lib/list.h>
#include <fs.h>

// 全局的文件系统指针
struct filesystem *file_systems;

// 初始化VFS目录树
static void init_mount_tree(struct vfsmount *mount);

// vfs 初始化
void vfs_init(void)
{
        cprintk(rc_black, rc_light_brown, "Init Virtual File System ...\n\n");

        struct vfsmount *mount;
        mount = kmalloc(sizeof(struct vfsmount));
        assert(mount != NULL, "vfs_init alloc vfsmount failed!");

        // 初始化VFS目录树
        init_mount_tree(mount);

        current->files.vfsmount = mount;
}

// 初始化VFS目录树
static void init_mount_tree(struct vfsmount *mount)
{
        // 添加根文件系统
        add_filesystem(&fs_ramfs);

        INIT_LIST_HEAD(&(fs_ramfs.fs_supers));

        // 获取根文件系统的超级块结构
        struct super_block *sb = alloc_super_block();
        bzero(sb, sizeof(struct super_block));
        
        // 将 super_block 添加到文件系统控制信息下
        list_add(&(sb->s_list), &(fs_ramfs.fs_supers));

        // 为根文件系统初始化超级块
        fs_ramfs.read_super(sb);

        // 初始化根结点 inode
        struct inode *inode = alloc_inode();
        bzero(inode, sizeof(struct inode));
        inode->i_sb = sb;

        // 初始化根结点 dentry
        struct dentry *dentry = alloc_dentry();
        atomic_set(&(dentry->d_count), 0);
        INIT_LIST_HEAD(&(dentry->d_subdirs));
        INIT_LIST_HEAD(&(dentry->d_child));

        dentry->d_status = 1;
        dentry->d_parent = NULL;
        dentry->d_sb = sb;
        dentry->d_inode = inode;
        dentry->is_mounted = 0;
        strcpy(dentry->d_name, "/");
        
        // 链接根节点 dentry
        sb->s_root = dentry;

        mount->mnt_devname = "RAM";
        mount->mnt_sb = sb;
        mount->mnt_root = dentry;
        mount->mnt_mountpoint = dentry;
        mount->mnt_parent = NULL;
}

// 添加文件系统
int add_filesystem(struct filesystem *fs)
{
        struct filesystem *p = file_systems;
        while (p) {
                if (strcmp(p->name, fs->name) == 0) {
                        return -1;
                }
                p = p->next;
        }

        fs->next = file_systems;
        file_systems = fs;

        return 0;
}

struct super_block *alloc_super_block(void)
{
        struct super_block *sb;

        sb = kmalloc(sizeof(struct super_block));
        assert(sb != NULL, "alloc super_block failed!");

        return sb;
}

struct super_block_ops *alloc_super_block_ops(void)
{
        struct super_block_ops *sb_ops;

        sb_ops = kmalloc(sizeof(struct super_block_ops));
        assert(sb_ops != NULL, "alloc super_block_ops failed!");

        return sb_ops;
}

struct inode *alloc_inode(void)
{
        struct inode *inode;

        inode = kmalloc(sizeof(struct inode));
        assert(inode != NULL, "alloc inode failed!");

        return inode;
}

struct inode_ops *alloc_inode_ops(void)
{
        struct inode_ops *inode_ops;

        inode_ops = kmalloc(sizeof(struct inode_ops));
        assert(inode_ops != NULL, "alloc inode_ops failed!");

        return inode_ops;
}

struct dentry *alloc_dentry(void)
{
        struct dentry *dentry;

        dentry = kmalloc(sizeof(struct dentry));
        assert(dentry != NULL, "alloc dentry failed!");

        return dentry;
}

struct dentry_ops *alloc_dentry_ops(void)
{
        struct dentry_ops *dentry_ops;

        dentry_ops = kmalloc(sizeof(struct dentry_ops));
        assert(dentry_ops != NULL, "alloc dentry_ops failed!");

        return dentry_ops;
}

struct file *alloc_file(void)
{
        struct file *file;

        file = kmalloc(sizeof(struct file));
        assert(file != NULL, "alloc file failed!");

        return file;
}

struct file_ops *alloc_file_ops(void)
{
        struct file_ops *file_ops;

        file_ops = kmalloc(sizeof(struct file_ops));
        assert(file_ops != NULL, "alloc file_ops failed!");

        return file_ops;
}

void free_super_block(struct super_block *sb)
{
        assert(sb != NULL, "free_super_block error, sb is NULL!");
        kfree(sb);
}

void free_super_block_ops(struct super_ops *sb_ops)
{
        assert(sb_ops != NULL, "free_super_block_ops error, sb_ops is NULL!");
        kfree(sb_ops);
}

void free_inode(struct inode *inode)
{
        assert(inode != NULL, "free_inode error, inode is NULL!");
        kfree(inode);
}

void free_inode_ops(struct inode_ops *inode_ops)
{
        assert(inode_ops != NULL, "free_inode_ops error, inode_ops is NULL!");
        kfree(inode_ops);
}

void free_dentry(struct dentry *dentry)
{
        assert(dentry != NULL, "free_dentry error, dentry is NULL!");
        kfree(dentry);
}

void free_dentry_ops(struct dentry_ops *dentry_ops)
{
        assert(dentry_ops != NULL, "free_dentry_ops error, detry_ops is NULL!");
        kfree(dentry_ops);
}

void free_file(struct file *file)
{
        assert(file != NULL, "free_file error, file is NULL!");
        kfree(file);
}

void free_file_ops(struct file_ops *file_ops)
{
        assert(file_ops != NULL, "free_file_ops error, file_ops is NULL!");
        kfree(file_ops);
}

// 打开文件
int vfs_open(const char *filename, uint32_t openflag)
{
        if (!filename || !openflag) {
                return 0;
        }

        return 0;
}

// 关闭文件
int vfs_close(int fd)
{
        return fd;
}

// 读取文件
int vfs_read(int fd, char *buff, size_t size)
{
        if (!buff || !size) {
                return 0;
        }

        return fd;
}

// 写入文件
int vfs_write(int fd, const char *buff, size_t size)
{
        if (!buff || !size) {
                return 0;
        }

        return fd;
}



================================================
FILE: include/block_dev.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  block_dev.h
 *
 *    Description:  块设备接口定义
 *
 *        Version:  1.0
 *        Created:  2015年02月07日 11时15分49秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_BLOCK_DEV_H_
#define INCLUDE_BLOCK_DEV_H_

#include <types.h>

typedef
enum io_type {
        IO_READ = 0,
        IO_WRITE = 1
} io_type_t;

typedef 
struct io_request {
        io_type_t io_type;       // IO操作类型
        uint32_t secno;          // 起始位置
        uint32_t nsecs;          // 读写数量
        void *buffer;            // 读写缓冲区
        uint32_t bsize;          // 缓冲区尺寸
} io_request_t;

// 块设备接口
typedef
struct block_dev {
        const char *name;               // 设备名称
        uint32_t block_size;            // 单位块大小
        struct block_ops {                              // 设备操作
                int (*init)(void);                      // 设备初始化
                bool (*device_valid)(void); 	        // 设备是否可用
                const char *(*get_desc)(void);          // 获取设备描述
                int (*get_nr_block)(void);              // 获得设备默认块数量
                int (*request)(io_request_t *);         // 设备操作请求
                int (*ioctl)(int, int);                 // 设备选项设置
        } ops;
        struct block_dev *next;                         // 块设备链
} block_dev_t;

// 全局块设备链表
extern block_dev_t *block_devs;

// 块设备初始化
void block_dev_init(void);

// 内核注册块设备
int add_block_dev(block_dev_t *bdev);

// IDE 设备结构
extern block_dev_t ide_main_dev;

#endif  // INCLUDE_BLOCK_DEV_H_


================================================
FILE: include/char_dev.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  char_dev.h
 *
 *    Description:  字符设备定义
 *
 *        Version:  1.0
 *        Created:  2015年02月07日 11时16分28秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_CHAR_DEV_H_
#define INCLUDE_CHAR_DEV_H_

#include <types.h>

// 字符设备接口
typedef
struct char_dev {
        const char *name;                               // 设备名称
        bool is_readable;                               // 设备是否可读
        bool is_writeable;                              // 设备是否可写
        struct char_ops {                               // 设备操作
                int (*init)(void);                      // 设备初始化
                bool (*device_valid)(void); 	        // 设备是否可用
                const char *(*get_desc)(void);          // 获取设备描述
                int (*read)(void *, uint32_t);          // 设备读取
                int (*write)(const void *, uint32_t);   // 设备写入
                int (*ioctl)(int, int);                 // 设备选项设置
        } ops;
        struct char_dev *next;                          // 字符设备链
} char_dev_t;

// 全局字符设备链表
extern char_dev_t *char_devs;

// 字符设备初始化
void char_dev_init(void);

// 内核注册字符设备
int add_char_dev(char_dev_t *cdev);

// Keyboard 设备结构
extern char_dev_t kboard_dev;

#endif  // INCLUDE_CHAR_DEV_H_


================================================
FILE: include/debug.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  debug.h
 *
 *    Description:  调试函数
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 11时45分02秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_DEBUG_H_
#define INCLUDE_DEBUG_H_

#include <arch.h>
#include <vargs.h>
#include <elf.h>
#include <errno.h>

// 内核代码段在内存中的起始和结束位置,在链接脚本中定义
extern uint8_t kern_init_text_start[];
extern uint8_t kern_init_text_end[];
extern uint8_t kern_init_data_start[];
extern uint8_t kern_init_data_end[];
extern uint8_t kern_text_start[];
extern uint8_t kern_text_end[];
extern uint8_t kern_data_start[];
extern uint8_t kern_data_end[];

#define assert(x, info)                                         \
        do {                                                    \
                if (!(x)) {                                     \
                        panic(info);                            \
                }                                               \
        } while (0)

// 初始化 Debug 信息
void debug_init(void);

// 输出 BIOS 提供的物理内存布局
void show_memory_map(void);

// 输出内核当前占据的内存地址
void show_kernel_memory_map(void);

// 打印当前的函数调用栈信息
void panic(const char *msg);

// 打印当前的段存器值
void print_cur_status(void);

// 内核的打印函数
void printk(const char *format, ...);

// 内核的打印函数(带颜色)
void cprintk(real_color_t back, real_color_t fore, const char *format, ...);

#endif  // INCLUDE_DEBUG_H_


================================================
FILE: include/device.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  device.h
 *
 *    Description:  外部设备相关
 *
 *        Version:  1.0
 *        Created:  2015年02月08日 11时46分35秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_DEVICE_H_
#define INCLUDE_DEVICE_H_

// 外部设备初始化
void device_init(void);

#endif  // INCLUDE_DEVICE_H_


================================================
FILE: include/elf.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  elf.h
 *
 *    Description:  elf 相关的定义
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 11时00分18秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_ELF_H_
#define INCLUDE_ELF_H_

#include <types.h>
#include <mboot.h>

#define ELF32_ST_TYPE(i) ((i)&0xf)

// ELF 格式区段头
typedef
struct elf_section_header_t {
        uint32_t name;
        uint32_t type;
        uint32_t flags;
        uint32_t addr;
        uint32_t offset;
        uint32_t size;
        uint32_t link;
        uint32_t info;
        uint32_t addralign;
        uint32_t entsize;
} __attribute__((packed)) elf_section_header_t;

// ELF 格式符号
typedef
struct elf_symbol_t {
        uint32_t name;
        uint32_t value;
        uint32_t size;
        uint8_t  info;
        uint8_t  other;
        uint16_t shndx;
} __attribute__((packed)) elf_symbol_t;

// ELF 信息
typedef
struct elf_t {
        elf_symbol_t *symtab;
        uint32_t symtabsz;
        const char *strtab;
        uint32_t strtabsz;
} elf_t;

#endif  // INCLUDE_ELF_H_


================================================
FILE: include/errno.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  errno.h
 *
 *    Description:  错误编号
 *
 *        Version:  1.0
 *        Created:  2014年11月12日 15时22分53秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_ERRNO_H_
#define INCLUDE_ERRNO_H_

#include <types.h>

#define E_UNSPECIFIED       1   // Unspecified or unknown problem
#define E_BAD_PROC          2   // Process doesn't exist or otherwise
#define E_INVAL             3   // Invalid parameter
#define E_NO_MEM            4   // Request failed due to memory shortage
#define E_NO_FREE_PROC      5   // Attempt to create a new process beyond
#define E_FAULT             6   // Memory fault

#define MAXERROR            6

// 获得错误号对应的字符串
const char *strerr(int errno);

#endif  // INCLUDE_ERRNO_H_


================================================
FILE: include/fs.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  fs.h
 *
 *    Description:  文件系统相关
 *
 *        Version:  1.0
 *        Created:  2015年02月08日 10时07分14秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_FS_H_
#define INCLUDE_FS_H_

#include <types.h>
#include <spinlock.h>
#include <block_dev.h>

#define RAMFS_T        0xA0
#define SFS_T          0xAA

// 前置声明
struct super_block;
struct super_ops;
struct inode;
struct inode_ops;
struct dentry;
struct dentry_ops;
struct file;
struct file_ops;

struct filesystem {
        const char *name;                                         // 文件系统名称
        uint8_t type;                                             // 文件系统类型
        struct super_block *(*read_super)(struct super_block *);  // 读取super_block
        struct list_head fs_supers;                               // super_block指针
        struct filesystem *next;                                  // 下一个文件系统
};

struct super_block {
        uint16_t s_type;                // 文件系统类型
        uint32_t s_inode_count;         // inode数量
        uint32_t s_block_count;         // block数量
        uint32_t s_block_size;          // block大小
        uint32_t s_max_file;            // 文件最大尺寸
        uint32_t s_root_inode;          // 根 inode

        void *impl_sb;                  // 指向具体文件系统的 super_block
        struct list_head s_list;        // super_block指针
        block_dev_t *bdev;              // 对应的块设备指针
        struct dentry *s_root;          // 根dentry
        struct super_block_ops *s_ops;  // super_block操作
};

struct super_block_ops {
        struct inode *(*alloc_inode)(struct super_block *);     // 获取inode
        void (*destroy_inode)(struct inode *);                  // 释放inode
        void (*write_super)(struct super_block *);              // 写回super_block
        int (*sync_fs)(struct super_block *);                   // 同步文件系统
};

#define S_DIR    0x1    // inode 目录类型
#define S_FILE   0x2    // inode 文件类型

struct inode {
        uint32_t i_type;                // inode 类型
        uint32_t i_ino;                 // 索引节点号
        time_t i_atime;                 // 文件最后一次访问时间
        time_t i_mtime;                 // 文件最后一次修改时间
        time_t i_ctime;                 // 文件首次创建时间
        uint32_t i_size;                // 文件字节数
        uint32_t i_blocks;              // 文件使用block数
        uint32_t i_bytes;               // 文件最后一个block的字节数
        
        void *impl_in;                  // 指向具体文件系统的 inode
        spinlock_t i_lock;              // inode自旋锁
        atomic_t i_count;               // 索引节点引用计数
        struct super_block *i_sb;       // super_blcok指针
        struct list_head i_list;        // inode 链
};

// inode相关操作
struct inode_ops {
        int (*create)(struct inode *, struct dentry *);         // 创建文件
        int (*rm)(struct inode *, struct dentry *);             // 删除文件
        int (*mkdir)(struct inode *, struct dentry *);          // 创建目录
        int (*rmdir)(struct inode *, struct dentry *);          // 删除目录
        int (*rename)(struct inode *, struct dentry *,          // 重命名
                        struct inode *, struct dentry *);
};

// 最长文件名
#define MAX_FILE_NAME   123

// 目录类型inode存储的目录数据块 sizeof = 128
struct dirent {
        char d_name[MAX_FILE_NAME+1];   // 目录项名称
        uint32_t inode;                 // 对应的 inode
};

struct dentry {
        atomic_t d_count;               // 引用计数
        spinlock_t d_lock;              // dentry项的自旋锁
        char d_name[MAX_FILE_NAME+1];   // 目录项名称
        uint32_t d_status;              // 目录项状态
        struct dentry *d_parent;        // 父目录指针
        struct list_head d_subdirs;     // 子目录链表头
        struct list_head d_child;       // 链接到父dentry的d_subdirs
        bool is_mounted;                // 是否被挂载设备
        struct super_block *d_sb;       // 目录项对应的super_blcok
        struct inode *d_inode;          // 链接到目录项对应的inode
        struct dentry_ops *d_ops;       // dentry相关操作
};

struct dentry_ops {
       int (*del)(struct dentry *); 
};

// 最长路径长度(含文件名)
#define MAX_PATH    1024

struct file {
        atomic_t f_count;               // 引用计数
        spinlock_t f_lock;              // file项的自旋锁
        char f_path[MAX_PATH+1];        // 文件路径
        struct dentry *f_dentry;        // 与文件相关的dentry
        uint32_t f_openflag;            // 打开文件时的标记
        uint32_t f_pos;                 // 文件操作的偏移
        struct file_ops *f_ops;         // 文件操作
};

struct file_ops {
        int (*read)(struct file *, char *, uint32_t);
        int (*write)(struct file *, const char *, uint32_t);
        int (*open)(struct inode *, struct file *);
        int (*fsync)(struct file *);
        int (*close)(struct inode *, struct file *);
};

// 进程最大打开的文件个数
#define MAX_OPEN_FILE   64

// 进程PCB里描述文件系统的结构
struct file_struct {
        spinlock_t fs_lock;                     // 同步修改保护锁
        struct vfsmount *vfsmount;              // 文件系统根结构
        struct file *file_array[MAX_OPEN_FILE]; // 进程打开的文件描述
};

struct vfsmount {
        const char *mnt_devname;         // 挂载的设备名称
        struct super_block *mnt_sb;      // 挂载的 super_block
        struct dentry *mnt_root;         // 挂载的根目录 dentry
        struct dentry *mnt_mountpoint;   // 挂载点 dentry
        struct vfsmount *mnt_parent;     // 父vfsmount指针
};

// 全局的文件系统指针
extern struct filesystem *file_systems; 

// 根文件系统
extern struct filesystem fs_ramfs;

// 文件系统初始化
void fs_init(void);

// 内核注册文件系统
int add_filesystem(struct filesystem *fs);

// 获取 super_block 结构
struct super_block *alloc_super_block(void);

// 获取 super_pos 结构
struct super_block_ops *alloc_super_block_ops(void);

// 获取 inode 结构
struct inode *alloc_inode(void);

// 获取 inode_ops 结构
struct inode_ops *alloc_inode_ops(void);

// 获取 dentry 结构
struct dentry *alloc_dentry(void);

// 获取 dentry_ops 结构
struct dentry_ops *alloc_dentry_ops(void);

// 获取 file 结构
struct file *alloc_file(void);

// 获取 file_ops 结构
struct file_ops *alloc_file_ops(void);

// 释放 super_block 结构
void free_super_block(struct super_block *sb);

// 释放 super_block_ops 结构
void free_super_block_ops(struct super_ops *sb_ops);

// 释放 inode 结构
void free_inode(struct inode *inode);

// 释放 inode_ops 结构
void free_inode_ops(struct inode_ops *inode_ops);

// 释放 dentry 结构
void free_dentry(struct dentry *dentry);

// 释放 dentry_ops 结构
void free_dentry_ops(struct dentry_ops *dentry_ops);

// 释放 file 结构
void free_file(struct file *file);

// 释放 file_ops 结构
void free_file_ops(struct file_ops *file_ops);

// 打开文件
int vfs_open(const char *filename, uint32_t openflag);

// 关闭文件
int vfs_close(int fd);

// 读取文件
int vfs_read(int fd, char *buff, size_t size);

// 写入文件
int vfs_write(int fd, const char *buff, size_t size);

#endif  // INCLUDE_FS_H_


================================================
FILE: include/init.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  init.h
 *
 *    Description:  内核初始化
 *
 *        Version:  1.0
 *        Created:  2015年05月31日 13时15分20秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_INIT_H_
#define INCLUDE_INIT_H_

// 体系结构无关的内核初始化函数
void kern_init(void);

#endif  // INCLUDE_INIT_H_


================================================
FILE: include/kio.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  kio.h
 *
 *    Description:  输入输出的实现
 *
 *        Version:  1.0
 *        Created:  2015年01月11日 17时15分20秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_KIO_H_
#define INCLUDE_KIO_H_

// 读取一个字符
char getchar(void);

#endif  // INCLUDE_KIO_H_


================================================
FILE: include/lib/list.h
================================================
/*
 * =====================================================================================
 *
 *           Filename:  list.h
 *
 *        Description:  模仿 Linux 内核的 list.h
 *
 *                Version:  1.0
 *                Created:  2014年11月08日 21时28分38秒
 *           Revision:  none
 *           Compiler:  gcc
 *
 *                 Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *                Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_LIB_LIST_H_
#define INCLUDE_LIB_LIST_H_

#include <types.h>

#define list_entry(ptr,type,member) (type *)((char *)ptr - __offsetof(type,member))

#define __offsetof(TYPE, MEMBER) ((unsigned int) &((TYPE *)0)->MEMBER)

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
        struct list_head name = LIST_HEAD_INIT(name)

static inline void INIT_LIST_HEAD(struct list_head *list)
{
        list->next = list;
        list->prev = list;
}

static inline void __list_add(struct list_head *new,
                struct list_head *prev, struct list_head *next)
{
        next->prev = new;
        new->next = next;
        new->prev = prev;
        prev->next = new;
}

static inline void list_add(struct list_head *new, struct list_head *head)
{
        __list_add(new, head, head->next);
}

static inline void list_add_before(struct list_head *new, struct list_head *head)
{
        __list_add(new, head->prev, head);
}

static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
        __list_add(new, head->prev, head);
}

static inline void __list_del(struct list_head * prev, struct list_head * next)
{
        next->prev = prev;
        prev->next = next;
}

static inline void list_del(struct list_head *entry)
{
        __list_del(entry->prev, entry->next);
}

static inline void list_replace(struct list_head *old,
                struct list_head *new)
{
        new->next = old->next;
        new->next->prev = new;
        new->prev = old->prev;
        new->prev->next = new;
}

static inline void list_replace_init(struct list_head *old,
                struct list_head *new)
{
        list_replace(old, new);
        INIT_LIST_HEAD(old);
}

static inline void list_del_init(struct list_head *entry)
{
        __list_del(entry->prev, entry->next);
        INIT_LIST_HEAD(entry);
}

static inline void list_move(struct list_head *list, struct list_head *head)
{
        __list_del(list->prev, list->next);
        list_add(list, head);
}

static inline void list_move_tail(struct list_head *list,
                struct list_head *head)
{
        __list_del(list->prev, list->next);
        list_add_tail(list, head);
}

static inline int list_is_last(const struct list_head *list,
                const struct list_head *head)
{
        return list->next == head;
}

static inline int list_empty(const struct list_head *head)
{
        return head->next == head;
}

static inline int list_empty_careful(const struct list_head *head)
{
        struct list_head *next = head->next;
        return (next == head) && (next == head->prev);
}

static inline int list_is_singular(const struct list_head *head)
{
        return !list_empty(head) && (head->next == head->prev);
}

static inline void __list_cut_position(struct list_head *list,
                struct list_head *head, struct list_head *entry)
{
        struct list_head *new_first = entry->next;
        list->next = head->next;
        list->next->prev = list;
        list->prev = entry;
        entry->next = list;
        head->next = new_first;
        new_first->prev = head;
}

static inline void list_cut_position(struct list_head *list,
                struct list_head *head, struct list_head *entry)
{
        if (list_empty(head))
                return;
        if (list_is_singular(head) &&
                        (head->next != entry && head != entry))
                return;
        if (entry == head)
                INIT_LIST_HEAD(list);
        else
                __list_cut_position(list, head, entry);
}

static inline void __list_splice(const struct list_head *list,
                struct list_head *prev, struct list_head *next)
{
        struct list_head *first = list->next;
        struct list_head *last = list->prev;

        first->prev = prev;
        prev->next = first;

        last->next = next;
        next->prev = last;
}

static inline void list_splice(const struct list_head *list,
                struct list_head *head)
{
        if (!list_empty(list))
                __list_splice(list, head, head->next);
}

static inline void list_splice_tail(struct list_head *list,
                struct list_head *head)
{
        if (!list_empty(list))
                __list_splice(list, head->prev, head);
}

static inline void list_splice_init(struct list_head *list,
                struct list_head *head)
{
        if (!list_empty(list)) {
                __list_splice(list, head, head->next);
                INIT_LIST_HEAD(list);
        }
}

static inline void list_splice_tail_init(struct list_head *list,
                struct list_head *head)
{
        if (!list_empty(list)) {
                __list_splice(list, head->prev, head);
                INIT_LIST_HEAD(list);
        }
}

#define list_first_entry(ptr, type, member)                         \
    list_entry((ptr)->next, type, member)

#define list_for_each(pos, head)                                    \
    for (pos = (head)->next; pos != (head); pos = pos->next)

#define list_for_each_prev(pos, head)                               \
    for (pos = (head)->prev; pos != (head); pos = pos->prev)

#define list_for_each_safe(pos, n, head)                            \
    for (pos = (head)->next, n = pos->next; pos != (head);          \
            pos = n, n = pos->next)

#define list_for_each_prev_safe(pos, n, head)                       \
    for (pos = (head)->prev, n = pos->prev;                         \
            pos != (head);                                          \
            pos = n, n = pos->prev)

#define list_for_each_entry(pos, head, member)                          \
    for (pos = list_entry((head)->next, typeof(*pos), member);          \
            &pos->member != (head);                                     \
            pos = list_entry(pos->member.next, typeof(*pos), member))

#define list_for_each_entry_reverse(pos, head, member)                  \
    for (pos = list_entry((head)->prev, typeof(*pos), member);          \
            pos->member != (head);                                      \
            pos = list_entry(pos->member.prev, typeof(*pos), member))

#define list_for_each_entry_safe(pos, n, head, member)                  \
    for (pos = list_entry((head)->next, typeof(*pos), member),          \
            n = list_entry(pos->member.next, typeof(*pos), member);     \
            &pos->member != (head);                                     \
            pos = n, n = list_entry(n->member.next, typeof(*n), member))

#define list_for_each_entry_reverse_safe(pos, n, head, member)          \
    for (pos = list_entry((head)->prev, typeof(*pos), member),          \
            n = list_entry(pos->member.next, typeof(*pos), member);     \
            &pos->member != (head);                                     \
            pos = n, n = list_entry(n->member.prev, typeof(*n), member))

#endif  // INCLUDE_LIB_LIST_H_


================================================
FILE: include/lib/rbtree.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  rbtree.h
 *
 *    Description:  红黑树的实现
 *
 *        Version:  1.0
 *        Created:  2014年11月12日 09时29分04秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_LIB_RBTREE_H_
#define INCLUDE_LIB_RBTREE_H_

/*
  Red Black Trees
  (C) 1999  Andrea Arcangeli <andrea@suse.de>
  
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  linux/include/linux/rbtree.h

  To use rbtrees you'll have to implement your own insert and search cores.
  This will avoid us to use callbacks and to drop drammatically performances.
  I know it's not the cleaner way,  but in C (not in C++) to get
  performances and genericity...

  Some example of insert and search follows here. The search is a plain
  normal search over an ordered tree. The insert instead must be implemented
  in two steps: First, the code must insert the element in order as a red leaf
  in the tree, and then the support library function rb_insert_color() must
  be called. Such function will do the not trivial work to rebalance the
  rbtree, if necessary.

-----------------------------------------------------------------------
static inline struct page * rb_search_page_cache(struct inode * inode,
                                                 unsigned long offset)
{
        struct rb_node * n = inode->i_rb_page_cache.rb_node;
        struct page * page;

        while (n)
        {
                page = rb_entry(n, struct page, rb_page_cache);

                if (offset < page->offset)
                        n = n->rb_left;
                else if (offset > page->offset)
                        n = n->rb_right;
                else
                        return page;
        }
        return NULL;
}

static inline struct page * __rb_insert_page_cache(struct inode * inode,
                                                   unsigned long offset,
                                                   struct rb_node * node)
{
        struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
        struct rb_node * parent = NULL;
        struct page * page;

        while (*p)
        {
                parent = *p;
                page = rb_entry(parent, struct page, rb_page_cache);

                if (offset < page->offset)
                        p = &(*p)->rb_left;
                else if (offset > page->offset)
                        p = &(*p)->rb_right;
                else
                        return page;
        }

        rb_link_node(node, parent, p);

        return NULL;
}

static inline struct page * rb_insert_page_cache(struct inode * inode,
                                                 unsigned long offset,
                                                 struct rb_node * node)
{
        struct page * ret;
        if ((ret = __rb_insert_page_cache(inode, offset, node)))
                goto out;
        rb_insert_color(node, &inode->i_rb_page_cache);
 out:
        return ret;
}
-----------------------------------------------------------------------
*/

#if defined(container_of)
  #undef container_of
  #define container_of(ptr, type, member) ({                    \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})
#else
  #define container_of(ptr, type, member) ({                    \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})
#endif

#if defined(offsetof)
  #undef offsetof
  #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#else 
  #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif

#undef NULL
#if defined(__cplusplus)
  #define NULL 0
#else
  #define NULL ((void *)0)
#endif

struct rb_node
{
        unsigned long  rb_parent_color;
#define RB_RED          0
#define RB_BLACK        1
        struct rb_node *rb_right;
        struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));
    /* The alignment might seem pointless, but allegedly CRIS needs it */

struct rb_root
{
        struct rb_node *rb_node;
};


#define rb_parent(r)   ((struct rb_node *)((r)->rb_parent_color & ~3))
#define rb_color(r)   ((r)->rb_parent_color & 1)
#define rb_is_red(r)   (!rb_color(r))
#define rb_is_black(r) rb_color(r)
#define rb_set_red(r)  do { (r)->rb_parent_color &= ~1; } while (0)
#define rb_set_black(r)  do { (r)->rb_parent_color |= 1; } while (0)

static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
{
        rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
}
static inline void rb_set_color(struct rb_node *rb, int color)
{
        rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}

#define RB_ROOT (struct rb_root) { NULL, }
#define rb_entry(ptr, type, member) container_of(ptr, type, member)

#define RB_EMPTY_ROOT(root)     ((root)->rb_node == NULL)
#define RB_EMPTY_NODE(node)     (rb_parent(node) == node)
#define RB_CLEAR_NODE(node)     (rb_set_parent(node, node))

static inline void rb_init_node(struct rb_node *rb)
{
        rb->rb_parent_color = 0;
        rb->rb_right = NULL;
        rb->rb_left = NULL;
        RB_CLEAR_NODE(rb);
}

extern void rb_insert_color(struct rb_node *, struct rb_root *);
extern void rb_erase(struct rb_node *, struct rb_root *);

typedef void (*rb_augment_f)(struct rb_node *node, void *data);

extern void rb_augment_insert(struct rb_node *node,
                              rb_augment_f func, void *data);
extern struct rb_node *rb_augment_erase_begin(struct rb_node *node);
extern void rb_augment_erase_end(struct rb_node *node,
                                 rb_augment_f func, void *data);

/* Find logical next and previous nodes in a tree */
extern struct rb_node *rb_next(const struct rb_node *);
extern struct rb_node *rb_prev(const struct rb_node *);
extern struct rb_node *rb_first(const struct rb_root *);
extern struct rb_node *rb_last(const struct rb_root *);

/* Fast replacement of a single node without remove/rebalance/add/rebalance */
extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, 
                            struct rb_root *root);

static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
                                struct rb_node ** rb_link)
{
        node->rb_parent_color = (unsigned long )parent;
        node->rb_left = node->rb_right = NULL;

        *rb_link = node;
}

#endif  // INCLUDE_LIB_RBTREE_H_


================================================
FILE: include/lib/string.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  string.h
 *
 *    Description:  字符串相关函数
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 11时02分12秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_LIB_STRING_H_
#define INCLUDE_LIB_STRING_H_

#include <types.h>

void memcpy(void *dest, void *src, uint32_t len);

void memset(void *dest, uint8_t val, uint32_t len);

void bzero(void *dest, uint32_t len);

int strcmp(const char *str1, const char *str2);

char *strcpy(char *dest, const char *src);

char *strncpy(char *dest, const char *src, uint32_t len);

char *strcat(char *dest, const char *src);

int strlen(const char *src);

#endif  // INCLUDE_LIB_STRING_H_


================================================
FILE: include/mboot.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  mboot.h
 *
 *    Description:  Multiboot 结构的定义
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 11时00分59秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_MULTIBOOT_H_
#define INCLUDE_MULTIBOOT_H_

#include <types.h>

/**
 * 启动后,在32位内核进入点,机器状态如下:
 *   1. CS 指向基地址为 0x00000000,限长为4G – 1的代码段描述符。
 *   2. DS,SS,ES,FS 和 GS 指向基地址为0x00000000,限长为4G – 1的数据段描述符。
 *   3. A20 地址线已经打开。
 *   4. 页机制被禁止。
 *   5. 中断被禁止。
 *   6. EAX = 0x2BADB002
 *   7. 系统信息和启动信息块的线性地址保存在 EBX中(相当于一个指针)。
 *      以下即为这个信息块的结构
 */

typedef
struct multiboot_t {
        uint32_t flags;                 // Multiboot 的版本信息
        /** 
         * 从 BIOS 获知的可用内存
         *
         * mem_lower和mem_upper分别指出了低端和高端内存的大小,单位是K。
         * 低端内存的首地址是0,高端内存的首地址是1M。
         * 低端内存的最大可能值是640K。
         * 高端内存的最大可能值是最大值减去1M。但并不保证是这个值。
         */
        uint32_t mem_lower;
        uint32_t mem_upper;

        uint32_t boot_device;           // 指出引导程序从哪个BIOS磁盘设备载入的OS映像
        uint32_t cmdline;               // 内核命令行
        uint32_t mods_count;            // boot 模块列表
        uint32_t mods_addr;
        
        /**
         * ELF 格式内核映像的section头表。
         * 包括每项的大小、一共有几项以及作为名字索引的字符串表。
         */
        uint32_t num;
        uint32_t size;
        uint32_t addr;
        uint32_t shndx;

        /**
         * 以下两项指出保存由BIOS提供的内存分布的缓冲区的地址和长度
         * mmap_addr是缓冲区的地址,mmap_length是缓冲区的总大小
         * 缓冲区由一个或者多个下面的大小/结构对 mmap_entry_t 组成
         */
        uint32_t mmap_length;           
        uint32_t mmap_addr;
        
        uint32_t drives_length;         // 指出第一个驱动器结构的物理地址       
        uint32_t drives_addr;           // 指出第一个驱动器这个结构的大小
        uint32_t config_table;          // ROM 配置表
        uint32_t boot_loader_name;      // boot loader 的名字
        uint32_t apm_table;             // APM 表
        uint32_t vbe_control_info;
        uint32_t vbe_mode_info;
        uint32_t vbe_mode;
        uint32_t vbe_interface_seg;
        uint32_t vbe_interface_off;
        uint32_t vbe_interface_len;
} __attribute__((packed)) multiboot_t;

/**
 * size是相关结构的大小,单位是字节,它可能大于最小值20
 * base_addr_low是启动地址的低32位,base_addr_high是高32位,启动地址总共有64位
 * length_low是内存区域大小的低32位,length_high是内存区域大小的高32位,总共是64位
 * type是相应地址区间的类型,1代表可用RAM,所有其它的值代表保留区域
 */
typedef
struct mmap_entry_t {
        uint32_t size;          // 留意 size 是不含 size 自身变量的大小
        uint32_t base_addr_low;
        uint32_t base_addr_high;
        uint32_t length_low;
        uint32_t length_high;
        uint32_t type;
} __attribute__((packed)) mmap_entry_t;

// type是相应地址区间的类型,1代表可用RAM,所有其它的值代表保留区域
#define MULTIBOOT_TYPE_RAM  1

// 声明全局的 multiboot_t * 指针
// 内核未建立分页机制前暂存的指针
extern multiboot_t *mboot_ptr_tmp;

// 内核页表建立后的指针
extern multiboot_t *glb_mboot_ptr;

#endif  // INCLUDE_MULTIBOOT_H_


================================================
FILE: include/mbr.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  mbr.h
 *
 *    Description:  MBR 信息定义
 *
 *        Version:  1.0
 *        Created:  2015年02月04日 10时40分13秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_MBR_H_
#define INCLUDE_MBR_H_

#include <types.h>
#include <block_dev.h>

#define SECTION_SIZE      512 	  // 扇区大小
#define MBR_CODE_LENGTH   446     // MBR代码长度
#define PARTITION_SIZE    16      // 分区表项大小
#define PARTITION_COUNT   4       // 分区表项目个数

typedef
struct partition_info_t {
        uint8_t active_flag;       // 活动分区标记(0x0表示非活动,0x80表示活动)
        uint8_t start_chs[3];      // 起始磁头号+扇区号+柱面号。磁头号1字节;扇区号2字节低6位;柱面号2字节高2位+3字节
        uint8_t partition_type;    // 分区类型
        uint8_t end_chs[3];        // 结束磁头号,含义同起始磁头号
        uint32_t start_sector;     // 逻辑起始扇区号
        uint32_t nr_sectors;       // 所占用扇区数
} __attribute__((packed)) partition_info_t;

typedef
struct mbr_info_t
{
        uint8_t  mbr_code[MBR_CODE_LENGTH];         // 主引导代码
        partition_info_t part[PARTITION_COUNT];     // 4 个主分区表信息
        uint16_t magic_num;                         // 魔数 0xAA55
} __attribute__((packed)) mbr_info_t;

// MBR信息
extern mbr_info_t mbr_info;

// 读取分区信息
int read_mbr_info(block_dev_t *bdev);

// 输出分区信息
void show_partition_info(void);

#endif  // INCLUDE_MBR_H_


================================================
FILE: include/mm/buddy_mm.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  buddy_mm.h
 *
 *    Description:  伙伴算法物理内存管理子系统
 *
 *        Version:  1.0
 *        Created:  2014年11月05日 11时36分16秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_MM_BUDDY_MM_H_
#define INCLUDE_MM_BUDDY_MM_H_

// 简单内存管理系统
extern struct pmm_manager buddy_mm_manager;

#endif  // INCLUDE_MM_BUDDY_MM_H_


================================================
FILE: include/mm/ff_mm.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  ff_mm.h
 *
 *    Description:  First-Fit 物理内存管理子系统
 *
 *        Version:  1.0
 *        Created:  2014年11月05日 11时36分16秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_MM_FF_MM_H_
#define INCLUDE_MM_FF_MM_H_

// 简单内存管理系统
extern struct pmm_manager ff_mm_manager;

#endif  // INCLUDE_MM_FF_MM_H_


================================================
FILE: include/mm/mm.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  mm.h
 *
 *    Description:  内存管理的头文件
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 13时31分10秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_MM_MM_H
#define INCLUDE_MM_MM_H

#include <mm/pmm.h>
#include <mm/vmm.h>
#include <mm/slob.h>

// 内存管理子系统初始化
void mm_init(void);

#endif  // INCLUDE_MM_MM_H


================================================
FILE: include/mm/slob.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  slob.h
 *
 *    Description:  slob 内存分配器
 *
 *        Version:  1.0
 *        Created:  2014年11月11日 15时39分57秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_MM_SLOB_H_
#define INCLUDE_MM_SLOB_H_

#include <types.h>

// slob 分配器初始化
void slob_init(void);

// 任意大小的内存分配函数
void *kmalloc(uint32_t size);

// 任意大小的内存释放函数
void kfree(void *addr);

#endif  // INCLUDE_MM_SLOB_H_


================================================
FILE: include/sched.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  sched.h
 *
 *    Description:  调度相关
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 15时07分07秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_SCHEDULING_H_
#define INCLUDE_SCHEDULING_H_

#include <arch.h>
#include <task/task.h>

// clock 中断回调函数
void clock_callback(pt_regs_t *regs);

// 任务调度
void schedule(void);

// 唤醒任务
void wakeup_task(struct task_struct *task);

#endif  // INCLUDE_SCHEDULING_H_


================================================
FILE: include/sync.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  sync.h
 *
 *    Description:  sync
 *
 *        Version:  1.0
 *        Created:  2014年11月06日 16时56分50秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
*/

#ifndef INCLUDE_SYNC_H_
#define INCLUDE_SYNC_H_

#include <common.h>
#include <types.h>
#include <arch.h>

static inline bool __intr_store(void)
{
        if (read_eflags() & FL_IF) {
                disable_intr();
                return true;
        }

        return false;
}

static inline void __intr_restore(bool flag)
{
        if (flag) {
                enable_intr();
        }
}

#define local_intr_store(x)      do { x = __intr_store(); } while (0)
#define local_intr_restore(x)   __intr_restore(x);

#endif  // INCLUDE_SYNC_H_



================================================
FILE: include/types.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  types.h
 *
 *    Description:  一些类型的定义
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 10时51分50秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_TYPES_H_
#define INCLUDE_TYPES_H_

#ifndef NULL
        #define NULL 0
#endif

#ifndef TRUE
        #define TRUE  1
        #define FALSE 0
#endif

#define __UNUSED__ __attribute__((unused))

typedef
enum bool {
        false = 0,
        true = 1
} bool;

typedef unsigned long long uint64_t;
typedef          long long int64_t;
typedef unsigned int       uint32_t;
typedef          int       int32_t;
typedef unsigned short     uint16_t;
typedef          short     int16_t;
typedef unsigned char      uint8_t;
typedef          char      int8_t;
typedef unsigned int       size_t;
typedef          int       ssize_t;

// 时间类型
typedef uint32_t time_t;

// 进程 PID
typedef int32_t pid_t;

// 页目录数据类型
typedef uint32_t pgd_t;

// 页表数据类型
typedef uint32_t pte_t;

// 原子类型
typedef
struct {
	volatile int counter;
} atomic_t;

// 内核链表类型
struct list_head {
        struct list_head *next, *prev;
};

#endif  // INCLUDE_TYPES_H_


================================================
FILE: include/vargs.h
================================================
/*
 * =====================================================================================
 *
 *       Filename:  vargs.h
 *
 *    Description:  可变形参表相关宏
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 11时44分02秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#ifndef INCLUDE_VARGS_H_
#define INCLUDE_VARGS_H_

typedef __builtin_va_list va_list;

#define va_start(ap, last)         (__builtin_va_start(ap, last))
#define va_arg(ap, type)           (__builtin_va_arg(ap, type))
#define va_end(ap) 

#endif  // INCLUDE_VARGS_H_


================================================
FILE: init/kmain.c
================================================
/*
 * =====================================================================================
 *
 *       Filename:  kmain.c
 *
 *    Description:  内核初始化
 *
 *        Version:  1.0
 *        Created:  2014年11月04日 10时05分01秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Qianyi.lh (liuhuan), qianyi.lh@alibaba-inc.com
 *        Company:  Alibaba-Inc Aliyun
 *
 * =====================================================================================
 */

#include <init.h>
#include <arch.h>
#in
Download .txt
gitextract_hd27az2o/

├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── arch/
│   ├── i386/
│   │   ├── debug/
│   │   │   └── debug.c
│   │   ├── driver/
│   │   │   ├── clock.c
│   │   │   ├── clock.h
│   │   │   ├── console.c
│   │   │   ├── console.h
│   │   │   ├── pic.c
│   │   │   └── pic.h
│   │   ├── include/
│   │   │   ├── arch.h
│   │   │   ├── atomic.h
│   │   │   ├── common.h
│   │   │   └── spinlock.h
│   │   ├── init/
│   │   │   ├── arch_init.c
│   │   │   ├── init.c
│   │   │   └── init_s.s
│   │   ├── intr/
│   │   │   ├── intr.c
│   │   │   ├── intr.h
│   │   │   └── intr_s.s
│   │   ├── mm/
│   │   │   ├── fault.c
│   │   │   ├── gdt.c
│   │   │   ├── gdt.h
│   │   │   ├── gdt_s.s
│   │   │   ├── pmm.c
│   │   │   ├── pmm.h
│   │   │   ├── vmm.c
│   │   │   └── vmm.h
│   │   ├── syscall/
│   │   │   ├── syscall.c
│   │   │   └── syscall.h
│   │   └── task/
│   │       ├── entry.s
│   │       ├── switch_to.s
│   │       ├── task.c
│   │       └── task.h
│   └── x64/
│       └── TODO
├── driver/
│   ├── block_dev.c
│   ├── char_dev.c
│   ├── device.c
│   ├── ide.c
│   └── kboard.c
├── fs/
│   ├── fs.c
│   ├── mbr.c
│   ├── ramfs/
│   │   └── ramfs.c
│   ├── sfs/
│   │   ├── sfs.c
│   │   └── sfs.h
│   └── vfs.c
├── include/
│   ├── block_dev.h
│   ├── char_dev.h
│   ├── debug.h
│   ├── device.h
│   ├── elf.h
│   ├── errno.h
│   ├── fs.h
│   ├── init.h
│   ├── kio.h
│   ├── lib/
│   │   ├── list.h
│   │   ├── rbtree.h
│   │   └── string.h
│   ├── mboot.h
│   ├── mbr.h
│   ├── mm/
│   │   ├── buddy_mm.h
│   │   ├── ff_mm.h
│   │   ├── mm.h
│   │   └── slob.h
│   ├── sched.h
│   ├── sync.h
│   ├── types.h
│   └── vargs.h
├── init/
│   └── kmain.c
├── isodir/
│   └── boot/
│       └── grub/
│           └── grub.cfg
├── kernel/
│   ├── errno.c
│   ├── kio.c
│   ├── printk.c
│   └── sched/
│       └── sched.c
├── lib/
│   ├── rbtree.c
│   └── string.c
├── mm/
│   ├── buddy_mm.c
│   ├── ff_mm.c
│   ├── mm.c
│   └── slob.c
└── scripts/
    ├── gdbinit
    └── kernel.ld
Download .txt
SYMBOL INDEX (433 symbols across 57 files)

FILE: arch/i386/debug/debug.c
  function debug_init (line 33) | void debug_init(void)
  function elf_from_multiboot (line 39) | static void elf_from_multiboot(multiboot_t *mb)
  function panic (line 58) | void panic(const char *msg)
  function print_stack_trace (line 70) | void print_stack_trace(void)
  function print_cur_status (line 97) | void print_cur_status(void)
  function show_memory_map (line 117) | void show_memory_map(void)
  function show_kernel_memory_map (line 134) | void show_kernel_memory_map(void)

FILE: arch/i386/driver/clock.c
  function clock_init (line 42) | void clock_init(void)

FILE: arch/i386/driver/console.c
  function console_init (line 75) | void console_init(void)
  function console_clear (line 82) | void console_clear(void)
  function move_cursor (line 107) | static void move_cursor(void)
  function scroll_buffer (line 118) | static void scroll_buffer(void)
  function console_putc_color (line 142) | static void console_putc_color(char c, real_color_t back, real_color_t f...
  function console_write (line 177) | void console_write(char *cstr)
  function console_write_color (line 191) | void console_write_color(char *cstr, real_color_t back, real_color_t fore)
  function _flush_console (line 205) | static void _flush_console(void)
  function _flush_console_current (line 232) | static void _flush_console_current(void)
  function console_view_up (line 243) | void console_view_up(uint16_t offset)
  function console_view_down (line 254) | void console_view_down(uint16_t offset)

FILE: arch/i386/driver/console.h
  type real_color_t (line 24) | typedef

FILE: arch/i386/driver/pic.c
  function init_interrupt_chip (line 30) | void init_interrupt_chip(void)
  function clear_interrupt_chip (line 64) | void clear_interrupt_chip(uint32_t intr_no)

FILE: arch/i386/include/atomic.h
  function set_bit (line 28) | static inline void set_bit(int32_t nr, volatile void *addr)
  function clear_bit (line 35) | static inline void clear_bit(int32_t nr, volatile void *addr)
  function change_bit (line 42) | static inline void change_bit(int32_t nr, volatile void *addr)
  function test_bit (line 49) | static inline bool test_bit(int32_t nr, volatile void *addr)
  function atomic_read (line 60) | static inline int32_t atomic_read(const atomic_t *v)
  function atomic_set (line 65) | static inline void atomic_set(atomic_t *v, int32_t i)
  function atomic_add (line 70) | static inline void atomic_add(atomic_t *v, int32_t i)
  function atomic_sub (line 77) | static inline void atomic_sub(atomic_t *v, int32_t i)
  function atomic_sub_and_test (line 84) | static inline int32_t atomic_sub_and_test(atomic_t *v, int32_t i)
  function atomic_inc (line 94) | static inline void atomic_inc(atomic_t *v)
  function atomic_inc_and_test (line 100) | static inline int32_t atomic_inc_and_test(atomic_t *v)
  function atomic_dec (line 110) | static inline void atomic_dec(atomic_t *v)
  function atomic_dec_and_test (line 116) | static inline int32_t atomic_dec_and_test(atomic_t *v)

FILE: arch/i386/include/common.h
  function outb (line 50) | static inline void outb(uint16_t port, uint8_t value)
  function inb (line 56) | static inline uint8_t inb(uint16_t port)
  function inw (line 66) | static inline uint16_t inw(uint16_t port)
  function insl (line 75) | static inline void insl(uint32_t port, void *addr, int cnt)
  function outsl (line 85) | static inline void outsl(uint32_t port, const void *addr, int cnt)
  function enable_intr (line 96) | static inline void enable_intr(void)
  function disable_intr (line 102) | static inline void disable_intr(void)
  function cpu_hlt (line 108) | static inline void cpu_hlt(void)
  function read_eflags (line 114) | static inline uint32_t read_eflags(void)
  function write_eflags (line 124) | static inline void write_eflags(uint32_t eflags)
  function switch_pgd (line 130) | static inline void switch_pgd(uint32_t pd)
  function tlb_reload_page (line 136) | static inline void tlb_reload_page(uint32_t va)
  function load_esp (line 142) | static inline void load_esp(uint32_t esp)

FILE: arch/i386/include/spinlock.h
  type spinlock_t (line 25) | typedef
  function spinlock_lock (line 37) | static inline void spinlock_lock(spinlock_t *lock)
  function spinlock_unlock (line 53) | static inline void spinlock_unlock(spinlock_t *lock)

FILE: arch/i386/init/arch_init.c
  function arch_init (line 22) | void arch_init(void)

FILE: arch/i386/init/init.c
  function kern_entry (line 46) | __attribute__((section(".init.text"))) void kern_entry(void)
  function mmap_tmp_page (line 68) | __attribute__((section(".init.text"))) void mmap_tmp_page(void)
  function enable_paging (line 95) | __attribute__((section(".init.text"))) void enable_paging(void)

FILE: arch/i386/intr/intr.c
  type idt_entry_t (line 26) | typedef
  type idt_ptr_t (line 36) | typedef
  function idt_init (line 78) | void idt_init(void)
  function idt_set_gate (line 99) | static void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8...
  function isr_handler (line 143) | void isr_handler(pt_regs_t *regs)
  function register_interrupt_handler (line 154) | void register_interrupt_handler(uint8_t n, interrupt_handler_t h)
  function irq_handler (line 160) | void irq_handler(pt_regs_t *regs)

FILE: arch/i386/intr/intr.h
  type pt_regs_t (line 25) | typedef

FILE: arch/i386/mm/fault.c
  function do_page_fault (line 24) | void do_page_fault(pt_regs_t *regs)

FILE: arch/i386/mm/gdt.c
  type gdt_entry_t (line 22) | typedef
  function gdt_set_gate (line 33) | __attribute__ ((aligned(8)));
  function tss_set_gate (line 49) | __attribute__ ((aligned(8)));
  type gdt_ptr_t (line 73) | typedef
  function gdt_init (line 83) | void gdt_init(void)

FILE: arch/i386/mm/gdt.h
  type tss_entry_t (line 52) | typedef

FILE: arch/i386/mm/pmm.c
  type pmm_manager (line 29) | struct pmm_manager
  function pmm_init (line 49) | void pmm_init(void)
  function get_ram_info (line 62) | static void get_ram_info(e820map_t *e820map)
  function phy_pages_init (line 80) | static void phy_pages_init(e820map_t *e820map)
  function page_t (line 125) | page_t *addr_to_page(uint32_t addr)
  function page_to_addr (line 132) | uint32_t page_to_addr(page_t *page)
  function page_init (line 139) | void page_init(page_t *pages, uint32_t n)
  function alloc_pages (line 144) | uint32_t alloc_pages(uint32_t n)
  function free_pages (line 156) | void free_pages(uint32_t addr, uint32_t n)
  function free_pages_count (line 165) | uint32_t free_pages_count(void)

FILE: arch/i386/mm/pmm.h
  type e820map_t (line 52) | typedef
  type mem_zone_t (line 65) | typedef
  type page_t (line 76) | typedef
  function page_ref (line 104) | static inline int32_t page_ref(page_t *page)
  function set_page_ref (line 109) | static inline void set_page_ref(page_t *page, int32_t val)
  function page_ref_inc (line 114) | static inline void page_ref_inc(page_t *page)
  function page_ref_dec (line 119) | static inline void page_ref_dec(page_t *page)
  type pmm_manager (line 131) | struct pmm_manager {

FILE: arch/i386/mm/vmm.c
  function vmm_init (line 31) | void vmm_init(void)
  function map (line 54) | void map(pgd_t *pgd_now, uint32_t va, uint32_t pa, uint32_t flags)
  function unmap (line 73) | void unmap(pgd_t *pgd_now, uint32_t va)
  function get_mapping (line 92) | uint32_t get_mapping(pgd_t *pgd_now, uint32_t va, uint32_t *pa)

FILE: arch/i386/mm/vmm.h
  type mm_struct (line 123) | struct mm_struct {
  type vma_struct (line 130) | struct vma_struct {

FILE: arch/i386/syscall/syscall.c
  function sys_test (line 26) | static int sys_test(uint32_t args[])
  function sys_exit (line 35) | static int sys_exit(uint32_t args[])
  function sys_fork (line 42) | static int sys_fork(uint32_t args[])
  function sys_read (line 49) | static int sys_read(uint32_t args[])
  function sys_write (line 58) | static int sys_write(uint32_t args[])
  function sys_open (line 67) | static int sys_open(uint32_t args[])
  function sys_close (line 75) | static int sys_close(uint32_t args[])
  function sys_getpid (line 82) | static int sys_getpid(uint32_t args[])
  function syscall_handler (line 101) | void syscall_handler(pt_regs_t *regs)

FILE: arch/i386/task/task.c
  type list_head (line 29) | struct list_head
  type task_struct (line 31) | struct task_struct
  type task_struct (line 32) | struct task_struct
  function pid_t (line 39) | static pid_t alloc_pid(void)
  function free_pid (line 56) | static void free_pid(pid_t pid)
  function task_init (line 64) | void task_init(void)
  function kernel_thread (line 89) | int kernel_thread(int (*func)(void *), void *args, uint32_t clone_flags)
  type context (line 105) | struct context
  type context (line 105) | struct context
  function task_run (line 107) | void task_run(struct task_struct *task)
  type task_struct (line 125) | struct task_struct
  type task_struct (line 129) | struct task_struct
  type task_struct (line 132) | struct task_struct
  type list_head (line 135) | struct list_head
  type task_struct (line 137) | struct task_struct
  function set_proc_name (line 147) | void set_proc_name(struct task_struct *task, char *name)
  type task_struct (line 153) | struct task_struct
  type task_struct (line 158) | struct task_struct
  type task_struct (line 159) | struct task_struct
  function copy_mm (line 168) | static int copy_mm(uint32_t clone_flags, struct task_struct *task)
  type pt_regs_t (line 178) | struct pt_regs_t
  function copy_thread (line 180) | static void copy_thread(struct task_struct *task, struct pt_regs_t *pt_r...
  function pid_t (line 192) | pid_t do_fork(uint32_t clone_flags, struct pt_regs_t *pt_regs)
  function do_exit (line 224) | void do_exit(int errno)
  function cpu_idle (line 240) | void cpu_idle(void)

FILE: arch/i386/task/task.h
  type task_state_t (line 34) | typedef
  type context (line 43) | struct context {
  type task_struct (line 59) | struct task_struct {
  type list_head (line 86) | struct list_head
  type task_struct (line 89) | struct task_struct
  type task_struct (line 92) | struct task_struct
  type task_struct (line 106) | struct task_struct
  type task_struct (line 112) | struct task_struct
  type task_struct (line 118) | struct task_struct
  type task_struct (line 121) | struct task_struct
  type pt_regs_t (line 125) | struct pt_regs_t

FILE: driver/block_dev.c
  function block_dev_init (line 28) | void block_dev_init(void)
  function add_block_dev (line 54) | int add_block_dev(block_dev_t *bdev)

FILE: driver/char_dev.c
  function char_dev_init (line 27) | void char_dev_init(void)
  function add_char_dev (line 37) | int add_char_dev(char_dev_t *cdev)

FILE: driver/device.c
  function device_init (line 24) | void device_init(void)

FILE: driver/ide.c
  type ide_device (line 74) | struct ide_device {
  function ide_wait_ready (line 120) | static int32_t ide_wait_ready(uint16_t iobase, bool check_error)
  function ide_init (line 140) | static int ide_init(void)
  function ide_device_valid (line 194) | static bool ide_device_valid(void)
  function ide_get_nr_block (line 200) | static int ide_get_nr_block(void)
  function ide_request (line 210) | static int ide_request(io_request_t *req)
  function ide_read_secs (line 228) | static int ide_read_secs(uint32_t secno, void *dst, uint32_t nsecs)
  function ide_write_secs (line 255) | static int ide_write_secs(uint32_t secno, const void *src, uint32_t nsecs)
  function ide_ioctl (line 282) | static int ide_ioctl(int op, int flag)

FILE: driver/kboard.c
  type key_status_t (line 50) | typedef uint8_t key_status_t;
  type keymap_t (line 52) | typedef
  type kboard_device (line 222) | struct kboard_device {
  function kb_init (line 231) | static int kb_init(void)
  function kb_device_valid (line 246) | static bool kb_device_valid(void)
  function kb_getchar (line 257) | static uint8_t kb_getchar(void)
  function kb_read (line 270) | static int kb_read(void *dec, uint32_t len)
  function kb_write (line 288) | static int kb_write(__UNUSED__ const void *src, __UNUSED__ uint32_t len)
  function keyboard_handler (line 294) | static void keyboard_handler(__UNUSED__ pt_regs_t *regs)
  function kb_ioctl (line 348) | static int kb_ioctl(int op, int flag)

FILE: fs/fs.c
  function fs_init (line 29) | void fs_init(void)

FILE: fs/mbr.c
  function read_mbr_info (line 26) | int read_mbr_info(block_dev_t *bdev)
  function show_partition_info (line 43) | void show_partition_info(void)

FILE: fs/ramfs/ramfs.c
  type super_block (line 22) | struct super_block
  type super_block (line 22) | struct super_block
  type filesystem (line 25) | struct filesystem
  type inode (line 32) | struct inode
  type super_block (line 32) | struct super_block
  type inode (line 35) | struct inode
  type super_block (line 38) | struct super_block
  type super_block (line 41) | struct super_block
  type super_block_ops (line 44) | struct super_block_ops
  type super_block (line 52) | struct super_block
  type super_block (line 52) | struct super_block
  type inode (line 61) | struct inode
  function ramfs_destroy_inode (line 67) | static void ramfs_destroy_inode(struct inode *inode)
  function ramfs_write_super (line 73) | static void ramfs_write_super(__UNUSED__ struct super_block *sb)
  function ramfs_sync_fs (line 79) | static int ramfs_sync_fs(__UNUSED__ struct super_block *sb)

FILE: fs/sfs/sfs.c
  type super_block (line 38) | struct super_block
  type super_block (line 56) | struct super_block
  type super_block (line 56) | struct super_block
  type sfs_super_block (line 59) | struct sfs_super_block
  type filesystem (line 95) | struct filesystem
  function sfs_init (line 102) | void sfs_init(void)
  function sfs_mkfs (line 127) | static void sfs_mkfs(uint32_t start_sec, uint32_t end_sec, uint32_t bloc...
  type super_block (line 179) | struct super_block
  type super_block (line 179) | struct super_block
  function sfs_write_super (line 187) | static void sfs_write_super(struct sfs_super_block *sb)
  function sfs_read_inode_map (line 192) | static int sfs_read_inode_map(void)
  function sfs_write_inode_map (line 200) | static void sfs_write_inode_map(void)
  function sfs_read_block_map (line 205) | static int sfs_read_block_map(void)
  function sfs_write_block_map (line 212) | static void sfs_write_block_map(void)
  function sfs_alloc_inode (line 217) | static uint32_t sfs_alloc_inode(void)
  function sfs_free_inode (line 223) | static void sfs_free_inode(uint32_t inode_no)
  function sfs_alloc_block (line 228) | static uint32_t sfs_alloc_block(void)
  function sfs_free_block (line 234) | static void sfs_free_block(uint32_t block_no)

FILE: fs/sfs/sfs.h
  type sfs_super_block (line 24) | struct sfs_super_block {
  type sfs_inode (line 45) | struct sfs_inode {
  type sfs_dirent (line 63) | struct sfs_dirent {

FILE: fs/vfs.c
  type filesystem (line 28) | struct filesystem
  type vfsmount (line 31) | struct vfsmount
  function vfs_init (line 34) | void vfs_init(void)
  function init_mount_tree (line 49) | static void init_mount_tree(struct vfsmount *mount)
  function add_filesystem (line 95) | int add_filesystem(struct filesystem *fs)
  type super_block (line 111) | struct super_block
  type super_block (line 113) | struct super_block
  type super_block (line 115) | struct super_block
  type super_block_ops (line 121) | struct super_block_ops
  type super_block_ops (line 123) | struct super_block_ops
  type super_block_ops (line 125) | struct super_block_ops
  type inode (line 131) | struct inode
  type inode (line 133) | struct inode
  type inode (line 135) | struct inode
  type inode_ops (line 141) | struct inode_ops
  type inode_ops (line 143) | struct inode_ops
  type inode_ops (line 145) | struct inode_ops
  type dentry (line 151) | struct dentry
  type dentry (line 153) | struct dentry
  type dentry (line 155) | struct dentry
  type dentry_ops (line 161) | struct dentry_ops
  type dentry_ops (line 163) | struct dentry_ops
  type dentry_ops (line 165) | struct dentry_ops
  type file (line 171) | struct file
  type file (line 173) | struct file
  type file (line 175) | struct file
  type file_ops (line 181) | struct file_ops
  type file_ops (line 183) | struct file_ops
  type file_ops (line 185) | struct file_ops
  function free_super_block (line 191) | void free_super_block(struct super_block *sb)
  function free_super_block_ops (line 197) | void free_super_block_ops(struct super_ops *sb_ops)
  function free_inode (line 203) | void free_inode(struct inode *inode)
  function free_inode_ops (line 209) | void free_inode_ops(struct inode_ops *inode_ops)
  function free_dentry (line 215) | void free_dentry(struct dentry *dentry)
  function free_dentry_ops (line 221) | void free_dentry_ops(struct dentry_ops *dentry_ops)
  function free_file (line 227) | void free_file(struct file *file)
  function free_file_ops (line 233) | void free_file_ops(struct file_ops *file_ops)
  function vfs_open (line 240) | int vfs_open(const char *filename, uint32_t openflag)
  function vfs_close (line 250) | int vfs_close(int fd)
  function vfs_read (line 256) | int vfs_read(int fd, char *buff, size_t size)
  function vfs_write (line 266) | int vfs_write(int fd, const char *buff, size_t size)

FILE: include/block_dev.h
  type io_type_t (line 24) | typedef
  type io_request_t (line 30) | typedef
  type block_dev_t (line 40) | typedef

FILE: include/char_dev.h
  type char_dev_t (line 25) | typedef

FILE: include/elf.h
  type elf_section_header_t (line 28) | typedef
  type elf_symbol_t (line 43) | typedef
  type elf_t (line 54) | typedef

FILE: include/fs.h
  type super_block (line 30) | struct super_block
  type super_ops (line 31) | struct super_ops
  type inode (line 32) | struct inode
  type inode_ops (line 33) | struct inode_ops
  type dentry (line 34) | struct dentry
  type dentry_ops (line 35) | struct dentry_ops
  type file (line 36) | struct file
  type file_ops (line 37) | struct file_ops
  type filesystem (line 39) | struct filesystem {
  type super_block (line 47) | struct super_block {
  type super_block_ops (line 62) | struct super_block_ops {
  type inode (line 72) | struct inode {
  type inode_ops (line 90) | struct inode_ops {
  type dirent (line 103) | struct dirent {
  type dentry (line 108) | struct dentry {
  type dentry_ops (line 122) | struct dentry_ops {
  type file (line 129) | struct file {
  type file_ops (line 139) | struct file_ops {
  type file_struct (line 151) | struct file_struct {
  type vfsmount (line 157) | struct vfsmount {
  type filesystem (line 166) | struct filesystem
  type filesystem (line 169) | struct filesystem
  type filesystem (line 175) | struct filesystem
  type super_block (line 178) | struct super_block
  type super_block_ops (line 181) | struct super_block_ops
  type inode (line 184) | struct inode
  type inode_ops (line 187) | struct inode_ops
  type dentry (line 190) | struct dentry
  type dentry_ops (line 193) | struct dentry_ops
  type file (line 196) | struct file
  type file_ops (line 199) | struct file_ops
  type super_block (line 202) | struct super_block
  type super_ops (line 205) | struct super_ops
  type inode (line 208) | struct inode
  type inode_ops (line 211) | struct inode_ops
  type dentry (line 214) | struct dentry
  type dentry_ops (line 217) | struct dentry_ops
  type file (line 220) | struct file
  type file_ops (line 223) | struct file_ops

FILE: include/lib/list.h
  function INIT_LIST_HEAD (line 33) | static inline void INIT_LIST_HEAD(struct list_head *list)
  function __list_add (line 39) | static inline void __list_add(struct list_head *new,
  function list_add (line 48) | static inline void list_add(struct list_head *new, struct list_head *head)
  function list_add_before (line 53) | static inline void list_add_before(struct list_head *new, struct list_he...
  function list_add_tail (line 58) | static inline void list_add_tail(struct list_head *new, struct list_head...
  function __list_del (line 63) | static inline void __list_del(struct list_head * prev, struct list_head ...
  function list_del (line 69) | static inline void list_del(struct list_head *entry)
  function list_replace (line 74) | static inline void list_replace(struct list_head *old,
  function list_replace_init (line 83) | static inline void list_replace_init(struct list_head *old,
  function list_del_init (line 90) | static inline void list_del_init(struct list_head *entry)
  function list_move (line 96) | static inline void list_move(struct list_head *list, struct list_head *h...
  function list_move_tail (line 102) | static inline void list_move_tail(struct list_head *list,
  function list_is_last (line 109) | static inline int list_is_last(const struct list_head *list,
  function list_empty (line 115) | static inline int list_empty(const struct list_head *head)
  function list_empty_careful (line 120) | static inline int list_empty_careful(const struct list_head *head)
  function list_is_singular (line 126) | static inline int list_is_singular(const struct list_head *head)
  function __list_cut_position (line 131) | static inline void __list_cut_position(struct list_head *list,
  function list_cut_position (line 143) | static inline void list_cut_position(struct list_head *list,
  function __list_splice (line 157) | static inline void __list_splice(const struct list_head *list,
  function list_splice (line 170) | static inline void list_splice(const struct list_head *list,
  function list_splice_tail (line 177) | static inline void list_splice_tail(struct list_head *list,
  function list_splice_init (line 184) | static inline void list_splice_init(struct list_head *list,
  function list_splice_tail_init (line 193) | static inline void list_splice_tail_init(struct list_head *list,

FILE: include/lib/rbtree.h
  type rb_node (line 140) | struct rb_node
  type rb_root (line 150) | struct rb_root
  function rb_set_parent (line 163) | static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
  function rb_set_color (line 167) | static inline void rb_set_color(struct rb_node *rb, int color)
  function rb_init_node (line 179) | static inline void rb_init_node(struct rb_node *rb)
  type rb_node (line 187) | struct rb_node
  type rb_root (line 187) | struct rb_root
  type rb_node (line 188) | struct rb_node
  type rb_root (line 188) | struct rb_root
  type rb_node (line 190) | struct rb_node
  type rb_node (line 192) | struct rb_node
  type rb_node (line 194) | struct rb_node
  type rb_node (line 194) | struct rb_node
  type rb_node (line 195) | struct rb_node
  type rb_node (line 199) | struct rb_node
  type rb_node (line 199) | struct rb_node
  type rb_node (line 200) | struct rb_node
  type rb_node (line 200) | struct rb_node
  type rb_node (line 201) | struct rb_node
  type rb_root (line 201) | struct rb_root
  type rb_node (line 202) | struct rb_node
  type rb_root (line 202) | struct rb_root
  type rb_node (line 205) | struct rb_node
  type rb_node (line 205) | struct rb_node
  type rb_root (line 206) | struct rb_root
  function rb_link_node (line 208) | static inline void rb_link_node(struct rb_node * node, struct rb_node * ...

FILE: include/mboot.h
  type multiboot_t (line 36) | typedef
  type mmap_entry_t (line 91) | typedef

FILE: include/mbr.h
  type partition_info_t (line 30) | typedef
  type mbr_info_t (line 40) | typedef

FILE: include/mm/buddy_mm.h
  type pmm_manager (line 23) | struct pmm_manager

FILE: include/mm/ff_mm.h
  type pmm_manager (line 23) | struct pmm_manager

FILE: include/sched.h
  type task_struct (line 32) | struct task_struct

FILE: include/sync.h
  function __intr_store (line 26) | static inline bool __intr_store(void)
  function __intr_restore (line 36) | static inline void __intr_restore(bool flag)

FILE: include/types.h
  type bool (line 34) | enum bool {
  type time_t (line 51) | typedef uint32_t time_t;
  type pid_t (line 54) | typedef int32_t pid_t;
  type pgd_t (line 57) | typedef uint32_t pgd_t;
  type pte_t (line 60) | typedef uint32_t pte_t;
  type atomic_t (line 63) | typedef
  type list_head (line 69) | struct list_head {

FILE: include/vargs.h
  type __builtin_va_list (line 22) | typedef __builtin_va_list va_list;

FILE: init/kmain.c
  function kern_init (line 31) | void kern_init(void)
  function init_main (line 59) | static int init_main(void *args)
  function user_mode_test_main (line 72) | static int user_mode_test_main(void *args)
  function kthread_test (line 91) | static void kthread_test(void)

FILE: kernel/kio.c
  function getchar (line 24) | char getchar(void)

FILE: kernel/printk.c
  function printk (line 26) | void printk(const char *format, ...)
  function cprintk (line 42) | void cprintk(real_color_t back, real_color_t fore, const char *format, ...)
  function skip_atoi (line 60) | static int skip_atoi(const char **s)
  function vsprintf (line 167) | static int vsprintf(char *buff, const char *format, va_list args)

FILE: kernel/sched/sched.c
  function clock_callback (line 25) | void clock_callback(__UNUSED__ pt_regs_t *regs)
  function schedule (line 30) | void schedule(void)
  function wakeup_task (line 66) | void wakeup_task(struct task_struct *task)

FILE: lib/rbtree.c
  function __rb_rotate_left (line 21) | static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
  function __rb_rotate_right (line 44) | static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
  function rb_insert_color (line 67) | void rb_insert_color(struct rb_node *node, struct rb_root *root)
  function __rb_erase_color (line 126) | static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
  function rb_erase (line 192) | void rb_erase(struct rb_node *node, struct rb_root *root)
  function rb_augment_path (line 257) | static void rb_augment_path(struct rb_node *node, rb_augment_f func, voi...
  function rb_augment_insert (line 280) | void rb_augment_insert(struct rb_node *node, rb_augment_f func, void *data)
  type rb_node (line 294) | struct rb_node
  type rb_node (line 294) | struct rb_node
  type rb_node (line 296) | struct rb_node
  function rb_augment_erase_end (line 319) | void rb_augment_erase_end(struct rb_node *node, rb_augment_f func, void ...
  type rb_node (line 328) | struct rb_node
  type rb_root (line 328) | struct rb_root
  type rb_node (line 330) | struct rb_node
  type rb_node (line 340) | struct rb_node
  type rb_root (line 340) | struct rb_root
  type rb_node (line 342) | struct rb_node
  type rb_node (line 352) | struct rb_node
  type rb_node (line 352) | struct rb_node
  type rb_node (line 354) | struct rb_node
  type rb_node (line 365) | struct rb_node
  type rb_node (line 380) | struct rb_node
  type rb_node (line 380) | struct rb_node
  type rb_node (line 382) | struct rb_node
  type rb_node (line 393) | struct rb_node
  function rb_replace_node (line 404) | void rb_replace_node(struct rb_node *victim, struct rb_node *new,

FILE: lib/string.c
  function memcpy (line 21) | inline void memcpy(void *dest, void *src, uint32_t len)
  function memset (line 32) | inline void memset(void *dest, uint8_t val, uint32_t len)
  function bzero (line 39) | inline void bzero(void *dest, uint32_t len)
  function strcmp (line 44) | inline int strcmp(const char *dest, const char *src)
  function strlen (line 106) | inline int strlen(const char *src)

FILE: mm/buddy_mm.c
  type pmm_manager (line 35) | struct pmm_manager
  type buddy_mm_struct (line 48) | struct buddy_mm_struct {
  type buddy_mm_struct (line 58) | struct buddy_mm_struct
  function buddy_page_init (line 68) | static void buddy_page_init(page_t *pages, uint32_t n)
  function get_order (line 104) | static uint32_t get_order(uint32_t size)
  function page_t (line 119) | static page_t *buddy_alloc_pages_sub(uint32_t order)
  function buddy_alloc_pages (line 148) | static uint32_t buddy_alloc_pages(uint32_t n)
  function page_to_idx (line 172) | static inline uint32_t page_to_idx(page_t *page)
  function page_t (line 177) | static inline page_t *idx_to_page(uint32_t idx)
  function page_is_buddy (line 182) | static bool page_is_buddy(page_t *page, uint32_t order)
  function buddy_free_pages_sub (line 191) | static void buddy_free_pages_sub(page_t *base, uint32_t order)
  function buddy_free_pages (line 218) | static void buddy_free_pages(uint32_t addr, uint32_t n)
  function buddy_free_pages_count (line 240) | static uint32_t buddy_free_pages_count(void)
  function buddy_show_memory_info (line 246) | static void buddy_show_memory_info(void)
  function buddy_show_management_info (line 255) | static void buddy_show_management_info(void)
  function buddy_test_mm (line 271) | static void buddy_test_mm(void)

FILE: mm/ff_mm.c
  type pmm_manager (line 35) | struct pmm_manager
  type ff_mm_struct (line 44) | struct ff_mm_struct {
  type ff_mm_struct (line 52) | struct ff_mm_struct
  function ff_page_init (line 58) | static void ff_page_init(page_t *pages, uint32_t n)
  function ff_alloc_pages (line 79) | static uint32_t ff_alloc_pages(uint32_t n)
  function ff_free_pages (line 120) | static void ff_free_pages(uint32_t addr, uint32_t n)
  function ff_free_pages_count (line 174) | static uint32_t ff_free_pages_count(void)
  function ff_show_memory_info (line 180) | static void ff_show_memory_info(void)
  function ff_show_management_info (line 187) | static void ff_show_management_info(void)
  function ff_test_mm (line 194) | static void ff_test_mm(void)

FILE: mm/mm.c
  function mm_init (line 21) | void mm_init(void)

FILE: mm/slob.c
  type slob_block_t (line 23) | typedef
  function slob_print (line 56) | static void slob_print(void)
  function __UNUSED__ (line 67) | __UNUSED__ static void slob_test(void)
  function slob_init (line 94) | void slob_init(void)
  function split_chunk (line 108) | static void split_chunk(slob_block_t *chunk_block, uint32_t len)
  function glue_chunk (line 123) | static void glue_chunk(slob_block_t *chunk_block)
  type list_head (line 153) | struct list_head
  function kfree (line 168) | void kfree(void *addr)
Condensed preview — 83 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (280K chars).
[
  {
    "path": ".gitignore",
    "chars": 287,
    "preview": "# Object files\n*.o\n*.ko\n*.obj\n*.elf\n.clang_complete\n\n# Precompiled Headers\n*.gch\n*.pch\n\n# Libraries\n*.lib\n*.a\n*.la\n*.lo\n"
  },
  {
    "path": "LICENSE",
    "chars": 18027,
    "preview": "GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundati"
  },
  {
    "path": "Makefile",
    "chars": 1825,
    "preview": "#!Makefile\n\n# --------------------------------------------------------\n#\n#    hurlex 这个小内核的 Makefile\n#\n#    默认使用的C语言编译器是"
  },
  {
    "path": "README.md",
    "chars": 87,
    "preview": "Hurlex II\n======\n\n一个运行在x86-IA32架构下的小内核,仅作为操作系统理论学习的参考。\n\n第二版重新设计和构思,参考一些优秀的实现进行补充设计和编码。\n"
  },
  {
    "path": "arch/i386/debug/debug.c",
    "chars": 4787,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  debug"
  },
  {
    "path": "arch/i386/driver/clock.c",
    "chars": 1589,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  clock"
  },
  {
    "path": "arch/i386/driver/clock.h",
    "chars": 600,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  clock"
  },
  {
    "path": "arch/i386/driver/console.c",
    "chars": 6649,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  conso"
  },
  {
    "path": "arch/i386/driver/console.h",
    "chars": 1373,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  conso"
  },
  {
    "path": "arch/i386/driver/pic.c",
    "chars": 1747,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  pic.c"
  },
  {
    "path": "arch/i386/driver/pic.h",
    "chars": 674,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  pic.h"
  },
  {
    "path": "arch/i386/include/arch.h",
    "chars": 712,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  arch."
  },
  {
    "path": "arch/i386/include/atomic.h",
    "chars": 3115,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  atomi"
  },
  {
    "path": "arch/i386/include/common.h",
    "chars": 3813,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  commo"
  },
  {
    "path": "arch/i386/include/spinlock.h",
    "chars": 1571,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  spinl"
  },
  {
    "path": "arch/i386/init/arch_init.c",
    "chars": 631,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  arch_"
  },
  {
    "path": "arch/i386/init/init.c",
    "chars": 2927,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  init."
  },
  {
    "path": "arch/i386/init/init_s.s",
    "chars": 2283,
    "preview": "; ----------------------------------------------------------------\n;\n;       init.s -- 内核从这里开始\n;\n;       qianyi.lh   201"
  },
  {
    "path": "arch/i386/intr/intr.c",
    "chars": 4829,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  intr."
  },
  {
    "path": "arch/i386/intr/intr.h",
    "chars": 4613,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  intr."
  },
  {
    "path": "arch/i386/intr/intr_s.s",
    "chars": 3453,
    "preview": "; --------------------------------------------------\n; \t将 IDT 地址 载入 IDTR\n;\n; \tqianyi.lh  2014/11/04  14:44:23\n;---------"
  },
  {
    "path": "arch/i386/mm/fault.c",
    "chars": 1835,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  fault"
  },
  {
    "path": "arch/i386/mm/gdt.c",
    "chars": 2996,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  gdt.c"
  },
  {
    "path": "arch/i386/mm/gdt.h",
    "chars": 2799,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  gdt.h"
  },
  {
    "path": "arch/i386/mm/gdt_s.s",
    "chars": 745,
    "preview": "; -------------------------------------------------\n;       GDTR 和 TR 相关操作\n;\n;       qianyi.lh  2014/11/04  14:15:54\n; -"
  },
  {
    "path": "arch/i386/mm/pmm.c",
    "chars": 5393,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  pmm.c"
  },
  {
    "path": "arch/i386/mm/pmm.h",
    "chars": 4159,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  pmm.h"
  },
  {
    "path": "arch/i386/mm/vmm.c",
    "chars": 3027,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  vmm.c"
  },
  {
    "path": "arch/i386/mm/vmm.h",
    "chars": 5156,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  vmm.h"
  },
  {
    "path": "arch/i386/syscall/syscall.c",
    "chars": 2642,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  sysca"
  },
  {
    "path": "arch/i386/syscall/syscall.h",
    "chars": 865,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  sysca"
  },
  {
    "path": "arch/i386/task/entry.s",
    "chars": 371,
    "preview": "; -------------------------------------------------\n;       内核创建线程的统一入口函数\n;\n;       qianyi.lh  2014/11/12  14:45:54\n; --"
  },
  {
    "path": "arch/i386/task/switch_to.s",
    "chars": 820,
    "preview": "; -------------------------------------------------\n; \t任务切换的实现\n;\n; \tqianyi.lh  2014/11/12  16:38:56\n;\n; ----------------"
  },
  {
    "path": "arch/i386/task/task.c",
    "chars": 6292,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  task."
  },
  {
    "path": "arch/i386/task/task.h",
    "chars": 3127,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  task."
  },
  {
    "path": "arch/x64/TODO",
    "chars": 5,
    "preview": "TODO\n"
  },
  {
    "path": "driver/block_dev.c",
    "chars": 1643,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  block"
  },
  {
    "path": "driver/char_dev.c",
    "chars": 1146,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  char_"
  },
  {
    "path": "driver/device.c",
    "chars": 635,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  devic"
  },
  {
    "path": "driver/ide.c",
    "chars": 8223,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  ide.c"
  },
  {
    "path": "driver/kboard.c",
    "chars": 10647,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  kboar"
  },
  {
    "path": "fs/fs.c",
    "chars": 678,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  fs.c\n"
  },
  {
    "path": "fs/mbr.c",
    "chars": 1940,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  mbr.c"
  },
  {
    "path": "fs/ramfs/ramfs.c",
    "chars": 1846,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  ramfs"
  },
  {
    "path": "fs/sfs/sfs.c",
    "chars": 6710,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  sfs.c"
  },
  {
    "path": "fs/sfs/sfs.h",
    "chars": 2282,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  sfs.h"
  },
  {
    "path": "fs/vfs.c",
    "chars": 6055,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  vfs.c"
  },
  {
    "path": "include/block_dev.h",
    "chars": 1792,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  block"
  },
  {
    "path": "include/char_dev.h",
    "chars": 1545,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  char_"
  },
  {
    "path": "include/debug.h",
    "chars": 1670,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  debug"
  },
  {
    "path": "include/device.h",
    "chars": 596,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  devic"
  },
  {
    "path": "include/elf.h",
    "chars": 1346,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  elf.h"
  },
  {
    "path": "include/errno.h",
    "chars": 1037,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  errno"
  },
  {
    "path": "include/fs.h",
    "chars": 6946,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  fs.h\n"
  },
  {
    "path": "include/init.h",
    "chars": 592,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  init."
  },
  {
    "path": "include/kio.h",
    "chars": 580,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  kio.h"
  },
  {
    "path": "include/lib/list.h",
    "chars": 7465,
    "preview": "/*\n * =====================================================================================\n *\n *           Filename:  l"
  },
  {
    "path": "include/lib/rbtree.h",
    "chars": 7388,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  rbtre"
  },
  {
    "path": "include/lib/string.h",
    "chars": 962,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  strin"
  },
  {
    "path": "include/mboot.h",
    "chars": 3078,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  mboot"
  },
  {
    "path": "include/mbr.h",
    "chars": 1570,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  mbr.h"
  },
  {
    "path": "include/mm/buddy_mm.h",
    "chars": 641,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  buddy"
  },
  {
    "path": "include/mm/ff_mm.h",
    "chars": 632,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  ff_mm"
  },
  {
    "path": "include/mm/mm.h",
    "chars": 649,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  mm.h\n"
  },
  {
    "path": "include/mm/slob.h",
    "chars": 709,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  slob."
  },
  {
    "path": "include/sched.h",
    "chars": 749,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  sched"
  },
  {
    "path": "include/sync.h",
    "chars": 1015,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  sync."
  },
  {
    "path": "include/types.h",
    "chars": 1413,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  types"
  },
  {
    "path": "include/vargs.h",
    "chars": 745,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  vargs"
  },
  {
    "path": "init/kmain.c",
    "chars": 2864,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  kmain"
  },
  {
    "path": "isodir/boot/grub/grub.cfg",
    "chars": 50,
    "preview": "menuentry \"hurlex\" {\n\tmultiboot /boot/hx_kernel\n}\n"
  },
  {
    "path": "kernel/errno.c",
    "chars": 1103,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  errno"
  },
  {
    "path": "kernel/kio.c",
    "chars": 822,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  kio.c"
  },
  {
    "path": "kernel/printk.c",
    "chars": 10079,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  print"
  },
  {
    "path": "kernel/sched/sched.c",
    "chars": 1929,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  sched"
  },
  {
    "path": "lib/rbtree.c",
    "chars": 14314,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  rbtre"
  },
  {
    "path": "lib/string.c",
    "chars": 2169,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  strin"
  },
  {
    "path": "mm/buddy_mm.c",
    "chars": 10070,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  buddy"
  },
  {
    "path": "mm/ff_mm.c",
    "chars": 6730,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  ff_mm"
  },
  {
    "path": "mm/mm.c",
    "chars": 580,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  mm.c\n"
  },
  {
    "path": "mm/slob.c",
    "chars": 4827,
    "preview": "/*\n * =====================================================================================\n *\n *       Filename:  slob."
  },
  {
    "path": "scripts/gdbinit",
    "chars": 54,
    "preview": "file hx_kernel\ntarget remote :1234\nbreak kern_entry\nc\n"
  },
  {
    "path": "scripts/kernel.ld",
    "chars": 1542,
    "preview": "/*\n *      kernel.ld -- 针对 kernel 格式所写的链接脚本\n *     \n *      qianyi.lh   2014/11/04  10:00:00\n */\n\nENTRY(start)\nSECTIONS\n"
  }
]

About this extraction

This page contains the full source code of the hurley25/Hurlex-II GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 83 files (242.1 KB), approximately 69.2k tokens, and a symbol index with 433 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!