2020-11-13

/* readsect - read a single sector at @secno into @dst */
/* 读取编号为secno的一个扇区到dst地址处 */
static void
readsect(void *dst扇区地址, uint32_t secno扇区编号) {
    // 等待磁盘准备就绪
    waitdisk();

    outb(0x1F2, 1);                         // count = 1  读取一个扇区
    outb(0x1F3, secno & 0xFF);
    outb(0x1F4, (secno >> 8) & 0xFF);
    outb(0x1F5, (secno >> 16) & 0xFF);
    outb(0x1F6, ((secno >> 24) & 0xF) | 0xE0);
    outb(0x1F7, 0x20);                      // 0x20为读取磁盘命令

    // 等待磁盘准备就绪
    waitdisk();

    // 读该扇区
    insl(0x1F0, dst, SECTSIZE / 4);  //insl每次读取4B,cnt读取次数为 扇区长度 / 4
}
/* *
 * readseg - read @count bytes at @offset from kernel into virtual address @va,
 * might copy more than asked.
 * 从内核的offset偏移处读取count个字节到虚拟地址va中,可能复制的字节数多于请求的count个
 * */
static void
readseg(uintptr_t va虚拟地址入口, uint32_t count读取的字节数, uint32_t offset内核偏移量) {
    uintptr_t end_va = va + count;  //读取地址尾部

    // 向下对准到磁盘边界
    va -= offset % SECTSIZE;

    // 将偏移量转为扇区号,内核始于扇区1
    uint32_t secno = (offset / SECTSIZE) + 1;

    // If this is too slow, we could read lots of sectors at a time.
    // We'd write more to memory than asked, but it doesn't matter --
    // we load in increasing order.
    for (; va < end_va; va += SECTSIZE, secno ++) {
        readsect((void *)va, secno);  //依次读取若干扇区
    }
}
#define ELF_MAGIC    0x464C457FU            // "\x7FELF" in little endian  ELF魔数,小端存储

/* ELF文件头 */
struct elfhdr {
    uint32_t e_magic;     // ELF魔数,7f 45 4c 46
    uint8_t e_elf[12];    // ELF格式信息,32/64位,大端/小端存储
    uint16_t e_type;      // 1=relocatable, 2=executable, 3=shared object, 4=core image
    uint16_t e_machine;   // ELF体系结构类型,3=x86, 4=68K, etc.
    uint32_t e_version;   // 文件版本,总为1
    uint32_t e_entry;     // 可执行程序入口虚拟地址
    uint32_t e_phoff;     // 程序头表在文件内的字节偏移量
    uint32_t e_shoff;     // 节头表在文件内的字节偏移量
    uint32_t e_flags;     // 处理器相关标识,通常为0
    uint16_t e_ehsize;    // ELF header文件头字节大小
    uint16_t e_phentsize; // 程序头表每个条目(entry)的字节大小
    uint16_t e_phnum;     // 程序头表条目数量,即段的个数
    uint16_t e_shentsize; // 节头表每个条目(entry)的字节大小
    uint16_t e_shnum;     // 节头表中条目的数量,即节的个数
    uint16_t e_shstrndx;  // string name table在节头表中的索引index
};
struct proghdr {
    uint32_t p_type;   // 段类型, 如可加载的代码段或数据段、动态链接信息段等
    uint32_t p_offset; // 本段在文件内的其实偏移
    uint32_t p_va;     // 本段在内存中的起始虚拟地址
    uint32_t p_pa;     // 本段在内存中的起始物理地址,不使用
    uint32_t p_filesz; // 本段在文件中的大小
    uint32_t p_memsz;  // 本段在内存中的大小(如果包含bss节,会更大)
    uint32_t p_flags;  // 本段相关的标志,如读/写/执行
    uint32_t p_align;  // 对齐,和硬件页大小一致;如果为0或1,表示不需要对齐。否则,p_align应该是2的正整数幂,p_va和p_offset在对p_align取模后应相等
};
#define ELFHDR          ((struct elfhdr *)0x10000)      // 暂存空间

void
bootmain(void) {
    // 从硬盘读取一页大小数据(4K)到内存0x10000地址处
    readseg((uintptr_t)ELFHDR可执行文件虚拟地址入口, SECTSIZE * 8读取的字节数, 0内核偏移量);

    // 通过ELF魔数检查是否为合法的ELF文件
    if (ELFHDR->e_magic != ELF_MAGIC) {
        goto bad;
    }

    struct proghdr *ph, *eph;

    // 加载每个程序头到内存中(忽略程序头的flags)
    ph = (struct proghdr *)((uintptr_t)ELFHDR + ELFHDR->e_phoff 程序头表在文件内的字节偏移量);  //程序头表首项指针
    eph = ph + ELFHDR->e_phnum程序头表数量(段的个数);  //程序头表尾指针,eph = ph + 3 * sizeof(struct proghdr)
    for (; ph < eph; ph ++) {
        // 依次将各个段加载到虚拟内存(此时虚拟内存 = 物理内存),内存地址固定在0x000000—0xFFFFFF之间
        readseg(ph->p_va & 0xFFFFFF, ph->p_memsz, ph->p_offset);
    }

    // 跳转到程序入口处执行,即0x100000处,(void (*)(void))addr为将addr(ELFHDR->e_entry &  
    // 0xFFFFFF)转换为无参数无返回值的函数指针,再调用函数指针执行该地址处的代码
    ((void (*)(void))(ELFHDR->e_entry可执行程序入口虚拟地址 & 0xFFFFFF))();

bad:
    //内核文件不是ELF文件,死循环
    outw(0x8A00, 0x8A00);
    outw(0x8A00, 0x8E00);

    /* do nothing */
    while (1);
}
这是一个 SQL 语句,用于向借阅表中插入数据。该表包含以下字段:借阅编号、读者编号、书籍编号、借阅日期、归还日期、借阅状态。每条数据表示一次借阅记录。其中借阅编号、读者编号、书籍编号、借阅日期和借阅状态是必填项,归还日期为可选项,如果借阅状态为“已还”则必须填写归还日期。 具体插入的数据如下: - 借阅编号:100001,读者编号:123413,书籍编号:0001,借阅日期:2020-11-05,归还日期:NULL,借阅状态:借阅 - 借阅编号:100002,读者编号:223411,书籍编号:0002,借阅日期:2020-9-28,归还日期:2020-10-13,借阅状态:已还 - 借阅编号:100003,读者编号:321123,书籍编号:1001,借阅日期:2020-7-01,归还日期:NULL,借阅状态:过期 - 借阅编号:100004,读者编号:321124,书籍编号:2001,借阅日期:2020-10-09,归还日期:2020-10-14,借阅状态:已还 - 借阅编号:100005,读者编号:321124,书籍编号:0001,借阅日期:2020-10-15,归还日期:NULL,借阅状态:借阅 - 借阅编号:100006,读者编号:223411,书籍编号:2001,借阅日期:2020-10-16,归还日期:NULL,借阅状态:借阅 - 借阅编号:100007,读者编号:411111,书籍编号:1002,借阅日期:2020-9-01,归还日期:2020-9-24,借阅状态:已还 - 借阅编号:100008,读者编号:411111,书籍编号:0001,借阅日期:2020-9-25,归还日期:NULL,借阅状态:借阅 - 借阅编号:100009,读者编号:411111,书籍编号:1001,借阅日期:2020-10-08,归还日期:NULL,借阅状态:借阅
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值