/* 将inode写入到分区part */ void inode_sync(struct partition* part, struct inode* inode, void* io_buf) { // io_buf是用于硬盘io的缓冲区 uint8_t inode_no = inode->i_no; struct inode_position inode_pos; inode_locate(part, inode_no, &inode_pos); // inode位置信息会存入inode_pos ASSERT(inode_pos.sec_lba <= (part->start_lba + part->sec_cnt)); /* 硬盘中的inode中的成员inode_tag和i_open_cnts是不需要的, * 它们只在内存中记录链表位置和被多少进程共享 */ struct inode pure_inode; memcpy(&pure_inode, inode, sizeof(struct inode)); /* 以下inode的三个成员只存在于内存中,现在将inode同步到硬盘,清掉这三项即可 */ pure_inode.i_open_cnts = 0; pure_inode.write_deny = false; // 置为false,以保证在硬盘中读出时为可写 pure_inode.inode_tag.prev = pure_inode.inode_tag.next = NULL; char* inode_buf = (char*)io_buf; if (inode_pos.two_sec) { // 若是跨了两个扇区,就要读出两个扇区再写入两个扇区 /* 读写硬盘是以扇区为单位,若写入的数据小于一扇区,要将原硬盘上的内容先读出来再和新数据拼成一扇区后再写入 */ ide_read(part->my_disk, inode_pos.sec_lba, inode_buf, 2); // inode在format中写入硬盘时是连续写入的,所以读入2块扇区 /* 开始将待写入的inode拼入到这2个扇区中的相应位置 */ memcpy((inode_buf + inode_pos.off_size), &pure_inode, sizeof(struct inode)); /* 将拼接好的数据再写入磁盘 */ ide_write(part->my_disk, inode_pos.sec_lba, inode_buf, 2); } else { // 若只是一个扇区 ide_read(part->my_disk, inode_pos.sec_lba, inode_buf, 1); memcpy((inode_buf + inode_pos.off_size), &pure_inode, sizeof(struct inode)); ide_write(part->my_disk, inode_pos.sec_lba, inode_buf, 1); } }
/* 在part分区内的pdir目录内寻找名为name的文件或目录, * 找到后返回true并将其目录项存入dir_e,否则返回false */ bool search_dir_entry(struct partition* part, struct dir* pdir, \ const char* name, struct dir_entry* dir_e) { uint32_t block_cnt = 140; // 12个直接块+128个一级间接块=140块 /* 12个直接块大小+128个间接块,共560字节 */ uint32_t* all_blocks = (uint32_t*)sys_malloc(48 + 512); if (all_blocks == NULL) { printk("search_dir_entry: sys_malloc for all_blocks failed"); return false; } uint32_t block_idx = 0; while (block_idx < 12) { all_blocks[block_idx] = pdir->inode->i_sectors[block_idx]; block_idx++; } block_idx = 0; if (pdir->inode->i_sectors[12] != 0) { // 若含有一级间接块表 ide_read(part->my_disk, pdir->inode->i_sectors[12], all_blocks + 12, 1); } /* 至此,all_blocks存储的是该文件或目录的所有扇区地址 */ /* 写目录项的时候已保证目录项不跨扇区, * 这样读目录项时容易处理, 只申请容纳1个扇区的内存 */ uint8_t* buf = (uint8_t*)sys_malloc(SECTOR_SIZE); struct dir_entry* p_de = (struct dir_entry*)buf; // p_de为指向目录项的指针,值为buf起始地址 uint32_t dir_entry_size = part->sb->dir_entry_size; uint32_t dir_entry_cnt = SECTOR_SIZE / dir_entry_size; // 1扇区内可容纳的目录项个数 /* 开始在所有块中查找目录项 */ while (block_idx < block_cnt) { /* 块地址为0时表示该块中无数据,继续在其它块中找 */ if (all_blocks[block_idx] == 0) { block_idx++; continue; } ide_read(part->my_disk, all_blocks[block_idx], buf, 1); uint32_t dir_entry_idx = 0; /* 遍历扇区中所有目录项 */ while (dir_entry_idx < dir_entry_cnt) { /* 若找到了,就直接复制整个目录项 */ if (!strcmp(p_de->filename, name)) { memcpy(dir_e, p_de, dir_entry_size); sys_free(buf); sys_free(all_blocks); return true; } dir_entry_idx++; p_de++; } block_idx++; p_de = (struct dir_entry*)buf; // 此时p_de已经指向扇区内最后一个完整目录项了,需要恢复p_de指向为buf memset(buf, 0, SECTOR_SIZE); // 将buf清0,下次再用 } sys_free(buf); sys_free(all_blocks); return false; }
// Fault any disk block that is read or written in to memory by // loading it from disk. // Hint: Use ide_read and BLKSECTS. static void bc_pgfault(struct UTrapframe *utf) { void *addr = (void *) utf->utf_fault_va; uint64_t blockno = ((uint64_t)addr - DISKMAP) / BLKSIZE; int r; // Check that the fault was within the block cache region if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) panic("page fault in FS: eip %08x, va %08x, err %04x", utf->utf_rip, addr, utf->utf_err); // Sanity check the block number. if (super && blockno >= super->s_nblocks) panic("reading non-existent block %08x\n", blockno); // Allocate a page in the disk map region, read the contents // of the block from the disk into that page, and mark the // page not-dirty (since reading the data from disk will mark // the page dirty). // // LAB 5: Your code here void *dst_addr = (void *) ROUNDDOWN(addr, BLKSIZE); r = sys_page_alloc(thisenv->env_id, dst_addr, PTE_U | PTE_P | PTE_W); // Project addition --> Transparent disk decryption (called only if disk block // is encrypted). Bitmap block has been left out of encryption, bitmap block data is tightly // bound in other routines, so can't encrypt. if(blockno == 2) ide_read(blockno * BLKSECTS, dst_addr, BLKSECTS); else if (blockno == 1) /* || (blockno == 2)) */ { if(!s_encrypted) ide_read(blockno * BLKSECTS, dst_addr, BLKSECTS); else { r = transparent_disk_decrypt(blockno, dst_addr); if(r) return; } } else { r = transparent_disk_decrypt(blockno, dst_addr); if(r) return; } // panic("bc_pgfault not implemented"); // Check that the block we read was allocated. (exercise for // the reader: why do we do this *after* reading the block // in?) if (bitmap && block_is_free(blockno)) panic("reading free block %08x\n", blockno); }
void ide_delay(uint8_t channel) { /* Each call delays 100 ns */ ide_read(channel, IDE_REGISTER_STATUS); ide_read(channel, IDE_REGISTER_STATUS); ide_read(channel, IDE_REGISTER_STATUS); ide_read(channel, IDE_REGISTER_STATUS); }
uint32_t loader() { Elf32_Ehdr *elf; Elf32_Phdr *ph = NULL; uint8_t buf[4096]; #ifdef HAS_DEVICE ide_read(buf, ELF_OFFSET_IN_DISK, 4096); #else ramdisk_read(buf, ELF_OFFSET_IN_DISK, 4096); #endif elf = (void*)buf; /* fix the magic number with the correct one */ const uint32_t elf_magic = 0x464c457f; uint32_t *p_magic = (void *)buf; nemu_assert(*p_magic == elf_magic); /* Load each program segment */ int i; for(i=0;i<elf->e_phnum;i++ ) { /* Scan the program header table, load each segment into memory */ ph=(void *)(elf->e_phoff + i * elf->e_phentsize + buf); if(ph->p_type == PT_LOAD) { //Log("success"); #ifdef IA32_PAGE /* Record the program break for future use. */ extern uint32_t brk; uint32_t new_brk = ph->p_vaddr + ph->p_memsz - 1; if(brk < new_brk) { brk = new_brk; } uint32_t pa=mm_malloc(ph->p_vaddr,ph->p_memsz); #endif #ifndef HAS_DEVICE ramdisk_read((void*)pa, ELF_OFFSET_IN_DISK + ph->p_offset, ph->p_filesz); #else ide_read((void*)pa, ELF_OFFSET_IN_DISK + ph->p_offset, ph->p_filesz); #endif memset((void*)(pa + ph->p_filesz), 0, ph->p_memsz - ph->p_filesz); } } volatile uint32_t entry = elf->e_entry; #ifdef IA32_PAGE mm_malloc(KOFFSET - STACK_SIZE, STACK_SIZE); #ifdef HAS_DEVICE create_video_mapping(); #endif write_cr3(get_ucr3()); #endif return entry; }
/* 在分区链表中找到名为part_name的分区,并将其指针赋值给cur_part */ static bool mount_partition(struct list_elem* pelem, int arg) { char* part_name = (char*)arg; struct partition* part = elem2entry(struct partition, part_tag, pelem); if (!strcmp(part->name, part_name)) { cur_part = part; struct disk* hd = cur_part->my_disk; /* sb_buf用来存储从硬盘上读入的超级块 */ struct super_block* sb_buf = (struct super_block*)sys_malloc(SECTOR_SIZE); /* 在内存中创建分区cur_part的超级块 */ cur_part->sb = (struct super_block*)sys_malloc(sizeof(struct super_block)); if (cur_part->sb == NULL) { PANIC("alloc memory failed!"); } /* 读入超级块 */ memset(sb_buf, 0, SECTOR_SIZE); ide_read(hd, cur_part->start_lba + 1, sb_buf, 1); /* 把sb_buf中超级块的信息复制到分区的超级块sb中。*/ memcpy(cur_part->sb, sb_buf, sizeof(struct super_block)); /********** 将硬盘上的块位图读入到内存 ****************/ cur_part->block_bitmap.bits = (uint8_t*)sys_malloc(sb_buf->block_bitmap_sects * SECTOR_SIZE); if (cur_part->block_bitmap.bits == NULL) { PANIC("alloc memory failed!"); } cur_part->block_bitmap.btmp_bytes_len = sb_buf->block_bitmap_sects * SECTOR_SIZE; /* 从硬盘上读入块位图到分区的block_bitmap.bits */ ide_read(hd, sb_buf->block_bitmap_lba, cur_part->block_bitmap.bits, sb_buf->block_bitmap_sects); /*************************************************************/ /********** 将硬盘上的inode位图读入到内存 ************/ cur_part->inode_bitmap.bits = (uint8_t*)sys_malloc(sb_buf->inode_bitmap_sects * SECTOR_SIZE); if (cur_part->inode_bitmap.bits == NULL) { PANIC("alloc memory failed!"); } cur_part->inode_bitmap.btmp_bytes_len = sb_buf->inode_bitmap_sects * SECTOR_SIZE; /* 从硬盘上读入inode位图到分区的inode_bitmap.bits */ ide_read(hd, sb_buf->inode_bitmap_lba, cur_part->inode_bitmap.bits, sb_buf->inode_bitmap_sects); /*************************************************************/ list_init(&cur_part->open_inodes); printk("mount %s done!\n", part->name); /* 此处返回true是为了迎合主调函数list_traversal的实现,与函数本身功能无关。 只有返回true时list_traversal才会停止遍历,减少了后面元素无意义的遍历.*/ return true; } return false; // 使list_traversal继续遍历 }
int fs_read(int fd, void *buf, int len) { int i=fd; if(file_state[i].offset+len>file_table[i-3].size) { int len_new=file_table[i-3].size-file_state[i].offset; ide_read(buf,file_table[i-3].disk_offset+file_state[i].offset,len_new); file_state[i].offset+=len_new; return len_new; } ide_read(buf,file_table[i-3].disk_offset+file_state[i].offset,len); file_state[i].offset+=len; return len; }
/* 根据i结点号返回相应的i结点 */ struct inode* inode_open(struct partition* part, uint32_t inode_no) { /* 先在已打开inode链表中找inode,此链表是为提速创建的缓冲区 */ struct list_elem* elem = part->open_inodes.head.next; struct inode* inode_found; while (elem != &part->open_inodes.tail) { inode_found = elem2entry(struct inode, inode_tag, elem); if (inode_found->i_no == inode_no) { inode_found->i_open_cnts++; return inode_found; } elem = elem->next; } /*由于open_inodes链表中找不到,下面从硬盘上读入此inode并加入到此链表 */ struct inode_position inode_pos; /* inode位置信息会存入inode_pos, 包括inode所在扇区地址和扇区内的字节偏移量 */ inode_locate(part, inode_no, &inode_pos); /* 为使通过sys_malloc创建的新inode被所有任务共享, * 需要将inode置于内核空间,故需要临时 * 将cur_pbc->pgdir置为NULL */ struct task_struct* cur = running_thread(); uint32_t* cur_pagedir_bak = cur->pgdir; cur->pgdir = NULL; /* 以上三行代码完成后下面分配的内存将位于内核区 */ inode_found = (struct inode*)sys_malloc(sizeof(struct inode)); /* 恢复pgdir */ cur->pgdir = cur_pagedir_bak; char* inode_buf; if (inode_pos.two_sec) { // 考虑跨扇区的情况 inode_buf = (char*)sys_malloc(1024); /* i结点表是被partition_format函数连续写入扇区的, * 所以下面可以连续读出来 */ ide_read(part->my_disk, inode_pos.sec_lba, inode_buf, 2); } else { // 否则,所查找的inode未跨扇区,一个扇区大小的缓冲区足够 inode_buf = (char*)sys_malloc(512); ide_read(part->my_disk, inode_pos.sec_lba, inode_buf, 1); } memcpy(inode_found, inode_buf + inode_pos.off_size, sizeof(struct inode)); /* 因为一会很可能要用到此inode,故将其插入到队首便于提前检索到 */ list_push(&part->open_inodes, &inode_found->inode_tag); inode_found->i_open_cnts = 1; sys_free(inode_buf); return inode_found; }
// Make sure a particular disk block is loaded into memory. // Returns 0 on success, or a negative error code on error. // // If blk != 0, set *blk to the address of the block in memory. // // Hint: Use diskaddr, map_block, and ide_read. static int read_block(uint32_t blockno, char **blk) { int r; char *addr; if (super && blockno >= super->s_nblocks) panic("reading non-existent block %08x\n", blockno); if (bitmap && block_is_free(blockno)) panic("reading free block %08x\n", blockno); addr = diskaddr(blockno); if(!block_is_mapped(blockno)){ if((r = map_block(blockno)) < 0) return r; r = ide_read(blockno*BLKSECTS, (void *)addr, BLKSECTS); if(r < 0) return r; } if(blk) *blk = addr; return 0; }
// Make sure a particular disk block is loaded into memory. // Returns 0 on success, or a negative error code on error. // // If blk != 0, set *blk to the address of the block in memory. // // Hint: Use diskaddr, map_block, and ide_read. static int read_block(uint32_t blockno, char **blk) { int r; char *addr; if (super && blockno >= super->s_nblocks) panic("reading non-existent block %08x\n", blockno); if (bitmap && block_is_free(blockno)) panic("reading free block %08x\n", blockno); // LAB 5: Your code here. addr = diskaddr(blockno); int error = map_block(blockno); if(error<0) return error; int secno = blockno*BLKSECTS; error = ide_read(secno, addr, (size_t)BLKSECTS); if(error) return error; if(blk) *blk = addr; // panic("read_block not implemented"); return 0; }
// Make sure a particular disk block is loaded into memory. // Returns 0 on success, or a negative error code on error. // // If blk != 0, set *blk to the address of the block in memory. // // Hint: Use diskaddr, map_block, and ide_read. static int read_block(uint32_t blockno, char **blk) { int r; char *addr; if (super && blockno >= super->s_nblocks) panic("reading non-existent block %08x\n", blockno); if (bitmap && block_is_free(blockno)) panic("reading free block %08x\n", blockno); // LAB 5: Your code here. addr = diskaddr(blockno); if(!block_is_mapped(blockno)){ if ((r = sys_page_alloc(sys_getenvid(), diskaddr(blockno), PTE_U|PTE_P|PTE_W)) < 0) return r; if((r = ide_read(blockno*(BLKSIZE/SECTSIZE), addr, (size_t) BLKSIZE/SECTSIZE)) < 0) return r; } if(blk != 0) *blk = addr; return 0; }
// Make sure a particular disk block is loaded into memory. // Returns 0 on success, or a negative error code on error. // // If blk != 0, set *blk to the address of the block in memory. // // Hint: Use diskaddr, map_block, and ide_read. static int read_block(uint32_t blockno, char **blk) { int r; char *addr; if (super && blockno >= super->s_nblocks) panic("reading non-existent block %08x\n", blockno); if (bitmap && block_is_free(blockno)) panic("reading free block %08x\n", blockno); // LAB 5: Your code here. addr = diskaddr(blockno); if (block_is_mapped(blockno)) { goto succeeded; } // now that the block is not in memory, allocate memory and read it in. if ((r = map_block(blockno)) < 0) return r; if ((r = ide_read(blockno * BLKSECTS, addr, BLKSECTS)) < 0) return r; succeeded: if (blk) *blk = addr; return 0; }
// Make sure a particular disk block is loaded into memory. // Returns 0 on success, or a negative error code on error. // // If blk != 0, set *blk to the address of the block in memory. // // Hint: Use diskaddr, map_block, and ide_read. static int read_block(uint32_t blockno, char **blk) { int r; char *addr; if (super && blockno >= super->s_nblocks) panic("reading non-existent block %08x\n", blockno); if (bitmap && block_is_free(blockno)) panic("reading free block %08x\n", blockno); // LAB 5: Your code here. r = map_block(blockno); if (r) return r; addr = diskaddr(blockno); r = ide_read(blockno * BLKSECTS, addr, BLKSECTS); if (r) return r; if (blk) *blk = addr; return sys_page_map(0, addr, 0, addr, vpt[VPN(addr)] & PTE_USER); }
// Fault any disk block that is read or written in to memory by // loading it from disk. // Hint: Use ide_read and BLKSECTS. static void bc_pgfault(struct UTrapframe *utf) { void *addr = (void *) utf->utf_fault_va; uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE; int r; // Check that the fault was within the block cache region if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) panic("page fault in FS: eip %08x, va %08x, err %04x", utf->utf_eip, addr, utf->utf_err); // Allocate a page in the disk map region and read the // contents of the block from the disk into that page. // // LAB 5: Your code here addr = ROUNDDOWN(addr, PGSIZE); if ((r = sys_page_alloc(0, addr, PTE_USER)) < 0) panic("sys_page_alloc: %e", r); if (ide_read(blockno * BLKSECTS, addr, BLKSECTS) < 0) panic("ide_read failed"); // Sanity check the block number. (exercise for the reader: // why do we do this *after* reading the block in?) if (super && blockno >= super->s_nblocks) panic("reading non-existent block %08x\n", blockno); // Check that the block we read was allocated. if (bitmap && block_is_free(blockno)) panic("reading free block %08x\n", blockno); }
/** * \brief Lee 512 bytes de un dispositivo * \param indexDevice * \param block * \param buffer * \return 1, si todo Ok, 0 en caso contrario */ int ReadBlock(int indexDevice, unsigned block, unsigned char* buffer) { unsigned status,err; if (!devices[indexDevice].existe) return 0; // voy a leer con lba28 unsigned lba0 = block & 0xFF; unsigned lba1 = (block & 0xFF00) >> 8; unsigned lba2 = (block & 0xFF0000) >> 16; unsigned devSelected = (block & 0xFF000000) >> 24; devSelected = (devices[indexDevice].slave << 4) | devSelected | 0x40; unsigned sectorCount = 1; // espero a que este desocupado el dispositivo while (ide_read(indexDevice, ATA_REG_STATUS) & ATA_SR_BSY); // ahora a leer el sector en cuestion ide_write(indexDevice,ATA_REG_SECCOUNT0, sectorCount); ide_write(indexDevice,ATA_REG_LBA0, lba0); ide_write(indexDevice,ATA_REG_LBA1, lba1); ide_write(indexDevice,ATA_REG_LBA2, lba2); ide_write(indexDevice,ATA_REG_HDDEVSEL, devSelected); ide_write(indexDevice,ATA_REG_COMMAND, ATA_CMD_READ_PIO); // ahora esperamos la disponibilidad de datos err = 0; while(!err) { status = ide_read(indexDevice, ATA_REG_STATUS); if (status & ATA_SR_ERR) err = 1; if (!err && !(status & ATA_SR_BSY) && (status & ATA_SR_DRDY)) // Everything is right. err = 2; } if (err == 1) { // ocurrio un error, debo analizarlo return 0; } // todo bien leamos los datos ide_read_data(indexDevice,buffer); return 1; }
uint32_t loader() { Elf32_Ehdr *elf; Elf32_Phdr *ph = NULL; uint8_t buf[4096]; #ifdef HAS_DEVICE ide_read(buf, ELF_OFFSET_IN_DISK, 4096); #else ramdisk_read(buf, ELF_OFFSET_IN_DISK, 4096); #endif elf = (void*)buf; /* TODO: fix the magic number with the correct one */ const uint32_t elf_magic = 0x7f454c46; uint32_t *p_magic = (void *)buf; nemu_assert(*p_magic == elf_magic); /* Load each program segment */ for(; true; ) { /* Scan the program header table, load each segment into memory */ if(ph->p_type == PT_LOAD) { //PT_LOAT=1, Loadable program segment /* TODO: read the content of the segment from the ELF file * to the memory region [VirtAddr, VirtAddr + FileSiz) */ /* TODO: zero the memory region * [VirtAddr + FileSiz, VirtAddr + MemSiz) */ #ifdef IA32_PAGE /* Record the program break for future use. */ extern uint32_t brk; uint32_t new_brk = ph->p_vaddr + ph->p_memsz - 1; if(brk < new_brk) { brk = new_brk; } #endif } } volatile uint32_t entry = elf->e_entry; #ifdef IA32_PAGE mm_malloc(KOFFSET - STACK_SIZE, STACK_SIZE); #ifdef HAS_DEVICE create_video_mapping(); #endif write_cr3(get_ucr3()); #endif return entry; }
int fs_read(int fd, void *buf, int len) { if (fd < 3) return 0; assert(file_state[fd].opened); if (file_state[fd].offset+len >= file_table[fd-3].size) len = file_table[fd-3].size-file_state[fd].offset-1; ide_read(buf, file_table[fd-3].disk_offset+file_state[fd].offset, len); file_state[fd].offset += len; return len; }
int fs_read(int fd, void *buf, int len) { //assert(state_array[i].opened == true); if(!state_array[fd].opened) return -1; int t = file_table[fd-3].size - state_array[fd].offset; len = len>t? t : len; ide_read(buf, file_table[fd-3].disk_offset + state_array[fd].offset, len); state_array[fd].offset += len; return len; }
//Borrowed from os dev really tired will write my own in future. unsigned char ide_polling(unsigned char channel, unsigned int advanced_check) { for(int i = 0; i < 4; i++) ide_read(channel, ATA_REG_ALTSTATUS); while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY) ; if (advanced_check) { unsigned char state = ide_read(channel, ATA_REG_STATUS); if (state & ATA_SR_ERROR) panic(); if (state & ATA_SR_DF) return 1; if ((state & ATA_SR_DRQ) == 0) return 3; } return 0; }
/* 回收inode的数据块和inode本身 */ void inode_release(struct partition* part, uint32_t inode_no) { struct inode* inode_to_del = inode_open(part, inode_no); ASSERT(inode_to_del->i_no == inode_no); /* 1 回收inode占用的所有块 */ uint8_t block_idx = 0, block_cnt = 12; uint32_t block_bitmap_idx; uint32_t all_blocks[140] = {0}; //12个直接块+128个间接块 /* a 先将前12个直接块存入all_blocks */ while (block_idx < 12) { all_blocks[block_idx] = inode_to_del->i_sectors[block_idx]; block_idx++; } /* b 如果一级间接块表存在,将其128个间接块读到all_blocks[12~], 并释放一级间接块表所占的扇区 */ if (inode_to_del->i_sectors[12] != 0) { ide_read(part->my_disk, inode_to_del->i_sectors[12], all_blocks + 12, 1); block_cnt = 140; /* 回收一级间接块表占用的扇区 */ block_bitmap_idx = inode_to_del->i_sectors[12] - part->sb->data_start_lba; ASSERT(block_bitmap_idx > 0); bitmap_set(&part->block_bitmap, block_bitmap_idx, 0); bitmap_sync(cur_part, block_bitmap_idx, BLOCK_BITMAP); } /* c inode所有的块地址已经收集到all_blocks中,下面逐个回收 */ block_idx = 0; while (block_idx < block_cnt) { if (all_blocks[block_idx] != 0) { block_bitmap_idx = 0; block_bitmap_idx = all_blocks[block_idx] - part->sb->data_start_lba; ASSERT(block_bitmap_idx > 0); bitmap_set(&part->block_bitmap, block_bitmap_idx, 0); bitmap_sync(cur_part, block_bitmap_idx, BLOCK_BITMAP); } block_idx++; } /*2 回收该inode所占用的inode */ bitmap_set(&part->inode_bitmap, inode_no, 0); bitmap_sync(cur_part, inode_no, INODE_BITMAP); /****** 以下inode_delete是调试用的 ****** * 此函数会在inode_table中将此inode清0, * 但实际上是不需要的,inode分配是由inode位图控制的, * 硬盘上的数据不需要清0,可以直接覆盖*/ void* io_buf = sys_malloc(1024); inode_delete(part, inode_no, io_buf); sys_free(io_buf); /***********************************************/ inode_close(inode_to_del); }
int fs_read(int fd, void *buf, size_t len) { if (fd < 3) return -1; assert(fd < NR_FILES + 3); assert(f_state[fd].opened); int max_len = file_table[fd - 3].size - f_state[fd].offset; assert(max_len >= 0); if (max_len < len) len = max_len; ide_read(buf, file_table[fd - 3].disk_offset + f_state[fd].offset, len); f_state[fd].offset += len; return len; }
// Fault any disk block that is read or written in to memory by // loading it from disk. // Hint: Use ide_read and BLKSECTS. static void bc_pgfault(struct UTrapframe *utf) { void *addr = (void *) utf->utf_fault_va; uint64_t blockno = ((uint64_t)addr - DISKMAP) / BLKSIZE; int r; // Check that the fault was within the block cache region if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) panic("page fault in FS: eip %08x, va %08x, err %04x", utf->utf_rip, addr, utf->utf_err); // Sanity check the block number. if (super && blockno >= super->s_nblocks) panic("reading non-existent block %08x\n", blockno); // Allocate a page in the disk map region, read the contents // of the block from the disk into that page, and mark the // page not-dirty (since reading the data from disk will mark // the page dirty). // // LAB 5: Your code here if((r= sys_page_alloc(0, ROUNDDOWN(addr,PGSIZE), PTE_SYSCALL)) < 0) panic("File System page fault handler couldn't alloc new page at addr %d. %e",addr, r); //if(super) // cprintf("12 %d\n",super->s_nblocks); #ifndef VMM_GUEST if((r = ide_read(blockno*BLKSECTS, ROUNDDOWN(addr,BLKSIZE), BLKSECTS)) < 0) #else if((r = host_read(BLKSECTS*blockno, ROUNDDOWN(addr,BLKSIZE), BLKSECTS)) < 0) #endif panic("File System page fault handler couldn't read in the data from disk. %e", r); //if(super) // cprintf("13 %d\n",super->s_nblocks); if((r = sys_page_map(0, ROUNDDOWN(addr,PGSIZE), 0, ROUNDDOWN(addr,BLKSIZE), PTE_P| PTE_U | PTE_W)) < 0) //PTE_SYSCALL&~PTE_D panic("Couldn't map page not dirty bc_pageflt %e",r); //if(super) // cprintf("14 %d\n",super->s_nblocks); //cprintf("Handled the Fault\n"); //panic("bc_pgfault not implemented"); // Check that the block we read was allocated. (exercise for // the reader: why do we do this *after* reading the block // in?) if (bitmap && block_is_free(blockno)) panic("reading free block %08x\n", blockno); }
/* 将硬盘分区part上的inode清空 */ void inode_delete(struct partition* part, uint32_t inode_no, void* io_buf) { ASSERT(inode_no < 4096); struct inode_position inode_pos; inode_locate(part, inode_no, &inode_pos); // inode位置信息会存入inode_pos ASSERT(inode_pos.sec_lba <= (part->start_lba + part->sec_cnt)); char* inode_buf = (char*)io_buf; if (inode_pos.two_sec) { // inode跨扇区,读入2个扇区 /* 将原硬盘上的内容先读出来 */ ide_read(part->my_disk, inode_pos.sec_lba, inode_buf, 2); /* 将inode_buf清0 */ memset((inode_buf + inode_pos.off_size), 0, sizeof(struct inode)); /* 用清0的内存数据覆盖磁盘 */ ide_write(part->my_disk, inode_pos.sec_lba, inode_buf, 2); } else { // 未跨扇区,只读入1个扇区就好 /* 将原硬盘上的内容先读出来 */ ide_read(part->my_disk, inode_pos.sec_lba, inode_buf, 1); /* 将inode_buf清0 */ memset((inode_buf + inode_pos.off_size), 0, sizeof(struct inode)); /* 用清0的内存数据覆盖磁盘 */ ide_write(part->my_disk, inode_pos.sec_lba, inode_buf, 1); } }
unsigned char ide_polling(unsigned char channel, unsigned int advanced_check) { // (I) Delay 400 nanosecond for BSY to be set: // ------------------------------------------------- int i; for(i = 0; i < 4; i++) ide_read(channel, ATA_REG_ALTSTATUS); // Reading the Alternate Status port wastes 100ns; loop four times. // (II) Wait for BSY to be cleared: // ------------------------------------------------- while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY) ; // Wait for BSY to be zero. if (advanced_check) { unsigned char state = ide_read(channel, ATA_REG_STATUS); // Read Status Register. // (III) Check For Errors: // ------------------------------------------------- if (state & ATA_SR_ERR) return 2; // Error. // (IV) Check If Device fault: // ------------------------------------------------- if (state & ATA_SR_DF) return 1; // Device Fault. // (V) Check DRQ: // ------------------------------------------------- // BSY = 0; DF = 0; ERR = 0 so we should check for DRQ now. if ((state & ATA_SR_DRQ) == 0) return 3; // DRQ should be set } return 0; // No Error. }
/* Read n sectors from the hard disk using PIO mode */ int ide_read(uint32 linear, uint32 numsects, void * bufptr) { int i; uint32 cyl,head,sector; if (numsects > 1) { for (i=0; i<numsects; i++) { if (ide_read(linear+i, 1, ((uint8 *)bufptr)+i*512) < 0) return -1; } } else { linear_to_chs(linear, &cyl, &head, §or); if (ide_read_chs(cyl, head, sector, numsects, (uint8*)bufptr) < 0) return -1; } return 0; }
// Fault any disk block that is read in to memory by // loading it from disk. static void bc_pgfault(struct UTrapframe *utf) { void *addr = (void *) utf->utf_fault_va; uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE; int r; // Check that the fault was within the block cache region if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) panic("page fault in FS: eip %08x, va %08x, err %04x", utf->utf_eip, addr, utf->utf_err); // Sanity check the block number. if (super && blockno >= super->s_nblocks) panic("reading non-existent block %08x\n", blockno); // Allocate a page in the disk map region, read the contents // of the block from the disk into that page. // Hint: first round addr to page boundary. fs/ide.c has code to read // the disk. // // LAB 5: you code here: addr = (void *)ROUNDDOWN(addr, PGSIZE); if ((r = sys_page_alloc(0, addr, PTE_P | PTE_U | PTE_W)) < 0) { panic("bc_pgfault: sys_page_alloc error %e\n", r); } if ((r = ide_read(BLKSECTS * blockno, addr, BLKSECTS)) < 0) { panic("bc_pgfault: ide_read error %e\n", r); } // Clear the dirty bit for the disk block page since we just read the // block from disk if ((r = sys_page_map(0, addr, 0, addr, uvpt[PGNUM(addr)] & PTE_SYSCALL)) < 0) panic("in bc_pgfault, sys_page_map: %e", r); // Check that the block we read was allocated. (exercise for // the reader: why do we do this *after* reading the block // in?) if (bitmap && block_is_free(blockno)) panic("reading free block %08x\n", blockno); }
// Fault any disk block that is read in to memory by // loading it from disk. // Hint: Use ide_read and BLKSECTS. static void bc_pgfault(struct UTrapframe *utf) { void *addr = (void *) utf->utf_fault_va; uint64_t blockno = ((uint64_t)addr - DISKMAP) / BLKSIZE; int r; // Check that the fault was within the block cache region if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) panic("page fault in FS: eip %08x, va %08x, err %04x", utf->utf_rip, addr, utf->utf_err); // Sanity check the block number. if (super && blockno >= super->s_nblocks) panic("reading non-existent block %08x\n", blockno); // Allocate a page in the disk map region, read the contents // of the block from the disk into that page. // Hint: first round addr to page boundary. // // LAB 5: your code here: addr = ROUNDDOWN(addr, PGSIZE); if(0 != sys_page_alloc(0, (void*)addr, PTE_SYSCALL)){ panic("Page Allocation Failed during handling page fault in FS"); } #ifdef VMM_GUEST if(0 != host_read((uint32_t) (blockno * BLKSECTS), (void*)addr, BLKSECTS)) { panic("ide read failed in Page Fault Handling"); } #else if(0 != ide_read((uint32_t) (blockno * BLKSECTS), (void*)addr, BLKSECTS)) { panic("ide read failed in Page Fault Handling"); } #endif if ((r = sys_page_map(0, addr, 0, addr, uvpt[PGNUM(addr)] & PTE_SYSCALL)) < 0) panic("in bc_pgfault, sys_page_map: %e", r); // Check that the block we read was allocated. (exercise for // the reader: why do we do this *after* reading the block // in?) if (bitmap && block_is_free(blockno)) panic("reading free block %08x\n", blockno); }
// Fault any disk block that is read in to memory by // loading it from disk. static void bc_pgfault(struct UTrapframe *utf) { void *addr = (void *) utf->utf_fault_va; uint64_t blockno = ((uint64_t)addr - DISKMAP) / BLKSIZE; int r; // Check that the fault was within the block cache region if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) panic("page fault in FS: eip %08x, va %08x, err %04x", utf->utf_rip, addr, utf->utf_err); // Sanity check the block number. if (super && blockno >= super->s_nblocks) panic("reading non-existent block %08x\n", blockno); // Allocate a page in the disk map region, read the contents // of the block from the disk into that page. // Hint: first round addr to page boundary. // // LAB 5: your code here: // Check that the block we read was allocated. (exercise for // the reader: why do we do this *after* reading the block // in?) if (bitmap && block_is_free(blockno)) //doubtful panic("reading free block %08x\n", blockno); void *new_addr = ROUNDDOWN(addr, PGSIZE); r = sys_page_alloc(0, new_addr, PTE_P|PTE_W|PTE_U); if(r<0) panic("Something wrong with allocation %e",r); uint64_t sec_no = BLKSECTS * blockno; size_t nsecs = BLKSECTS; #ifdef VMM_GUEST r = host_read(sec_no, new_addr, nsecs); #else r = ide_read(sec_no, new_addr, nsecs); #endif if(r<0) panic("Something wrong with reading from the disk %e",r); }
void kmain(ol_mmap_register_t mmr) { textinit(); clearscreen(); println("The openLoader kernel is executing. \n"); print("Current stack pointer: "); ol_registers_t regs = getregs(); printnum(regs->esp, 16, FALSE, FALSE); putc(0xa); char status = inb(0x60); if((status & 2) == 2) { println("The A20 gate is open."); putc(0xa); } pic_init(); setIDT(); outb(OL_KBC_COMMAND, OL_KB_INIT); // enable the keyboard // display mmap init_mmap(mmr); println("Multiboot memory map:\n"); display_mmap(mmr); #if 0 uint8_t active = ide_init(bootdrive); ide_read(0x100, 1<<20, &bootdrive[active], 60); uint8_t eax = ata_identify(); printnum(active, 16, FALSE, FALSE); #endif putc(0xa); println("Waiting for service interrupts.."); while(1) halt(); println("End of program reached!"); endprogram(); }
static LONG ide_identify(WORD dev) { LONG ret; UWORD ifnum, ifdev; ifnum = dev / 2; /* i.e. primary IDE, secondary IDE, ... */ ifdev = dev & 1; /* 0 or 1 */ KDEBUG(("ide_identify(%d [ifnum=%d ifdev=%d])\n", dev, ifnum, ifdev)); if (ide_device_exists(dev)) { ret = ide_read(IDE_CMD_IDENTIFY_DEVICE,ifnum,ifdev,0L,1, (UBYTE *)&identify,IDE_DATA_REGISTER_IS_BYTESWAPPED); } else ret = EUNDEV; if (ret < 0) KDEBUG(("ide_identify(%d [ifnum=%d ifdev=%d]) ret=%ld\n", dev, ifnum, ifdev, ret)); return ret; }