From 9221f2e1066eb2fddeb747fc01ed46e135ea0cdd Mon Sep 17 00:00:00 2001 From: xiaoyi1212 Date: Sat, 18 May 2024 23:44:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=87=E4=BB=B6=E7=B3=BB=E7=BB=9F=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.py | 6 +- driver/ide.c | 323 +++++------ driver/keyboard.c | 5 +- driver/vdisk.c | 129 ++--- fs/fat.c | 1302 ++++++++++++++++++++++++++++++++++++++++++ fs/iso9660.c | 328 +++++++++++ fs/vfs.c | 103 +++- include/arp.h | 2 +- include/common.h | 2 +- include/fat.h | 110 ++++ include/ide.h | 16 +- include/iso9660.h | 169 ++++++ include/pcnet.h | 12 +- include/timer.h | 1 + include/vdisk.h | 2 +- include/vfs.h | 4 + kernel/idt.c | 7 +- kernel/kernel.c | 14 +- kernel/timer.c | 4 + network/arp.c | 39 +- network/dhcp.c | 20 +- network/etherframe.c | 4 +- network/pcnet.c | 131 ++++- sysapp/shell.c | 158 +++-- util/common.c | 11 +- 25 files changed, 2557 insertions(+), 345 deletions(-) create mode 100644 fs/fat.c create mode 100644 fs/iso9660.c create mode 100644 include/fat.h create mode 100644 include/iso9660.h diff --git a/build.py b/build.py index d20f6da..3bb32f7 100644 --- a/build.py +++ b/build.py @@ -1,7 +1,7 @@ import os import sys -gcc = '/i686_elf_tools/bin/i686-elf-gcc.exe -std=gnu99 -I include/ -std=gnu99 -ffreestanding -O2 -c -Wincompatible-pointer-types' +gcc = '/i686_elf_tools/bin/i686-elf-gcc.exe -w -std=gnu99 -I include/ -std=gnu99 -ffreestanding -O0 -c -Wincompatible-pointer-types' asm = '/i686_elf_tools/bin/i686-elf-as.exe' nasm = "nasm -f elf32" ld = '/i686_elf_tools/bin/i686-elf-ld.exe' @@ -127,7 +127,7 @@ print("Launching i386 vm...") if len(sys.argv) == 0 or sys.argv[1] == 'vga': print("Graphics MODE [VGA]") - os.system("qemu-system-i386 -net nic,model=pcnet -net user -kernel isodir\\sys\\kernel.elf -drive format=qcow2,file=cpos.qcow2") + os.system("qemu-system-i386 -net nic,model=pcnet -net user -kernel isodir\\sys\\kernel.elf -hda diskx.img") elif sys.argv[1] == 'vbe': print("Graphics MODE [VBE]") - os.system("qemu-system-i386 -vga std -net nic,model=pcnet -net user -kernel isodir\\sys\\kernel.elf -drive format=qcow2,file=cpos.qcow2") \ No newline at end of file + os.system("qemu-system-i386 -vga std -net nic,model=pcnet -net user -kernel isodir\\sys\\kernel.elf -hda diskx.img") \ No newline at end of file diff --git a/driver/ide.c b/driver/ide.c index 5eb07db..b1b410a 100644 --- a/driver/ide.c +++ b/driver/ide.c @@ -8,7 +8,6 @@ static inline nul(char *f, ...) {} #define logk nul - #define inb io_in8 #define outb io_out8 @@ -46,12 +45,134 @@ static inline void insl(uint32_t port, uint32_t *addr, int cnt) { static void Read(char drive, unsigned char *buffer, unsigned int number, unsigned int lba) { - ide_read_sectors(drive - 'C', number, lba, 1 * 8, buffer); + ide_read_sectors(drive - 'A', number, lba, 1 * 8, buffer); } static void Write(char drive, unsigned char *buffer, unsigned int number, unsigned int lba) { - ide_write_sectors(drive - 'C', number, lba, 1 * 8, buffer); + ide_write_sectors(drive - 'A', number, lba, 1 * 8, buffer); +} + +void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2, + unsigned int BAR3, unsigned int BAR4) { + int j, k, count = 0; + for (int i = 0; i < 4; i++) { + ide_devices[i].Reserved = 0; + } + // 1- Detect I/O Ports which interface IDE Controller: + channels[ATA_PRIMARY].base = (BAR0 & 0xFFFFFFFC) + 0x1F0 * (!BAR0); + channels[ATA_PRIMARY].ctrl = (BAR1 & 0xFFFFFFFC) + 0x3F6 * (!BAR1); + channels[ATA_SECONDARY].base = (BAR2 & 0xFFFFFFFC) + 0x170 * (!BAR2); + channels[ATA_SECONDARY].ctrl = (BAR3 & 0xFFFFFFFC) + 0x376 * (!BAR3); + channels[ATA_PRIMARY].bmide = (BAR4 & 0xFFFFFFFC) + 0; // Bus Master IDE + channels[ATA_SECONDARY].bmide = (BAR4 & 0xFFFFFFFC) + 8; // Bus Master IDE + // 2- Disable IRQs: + ide_write(ATA_PRIMARY, ATA_REG_CONTROL, 2); + ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 2); + logk("w1\n"); + // 3- Detect ATA-ATAPI Devices: + for (int i = 0; i < 2; i++) + for (j = 0; j < 2; j++) { + unsigned char err = 0, type = IDE_ATA, status; + ide_devices[count].Reserved = 0; // Assuming that no drive here. + + // (I) Select Drive: + ide_write(i, ATA_REG_HDDEVSEL, 0xA0 | (j << 4)); // Select Drive. + sleep(1); // Wait 1ms for drive select to work. + logk("I\n"); + // (II) Send ATA Identify Command: + ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY); + sleep(1); // This function should be implemented in your OS. which waits + // for 1 ms. it is based on System Timer Device Driver. + logk("II\n"); + // (III) Polling: + if (ide_read(i, ATA_REG_STATUS) == 0) + continue; // If Status = 0, No Device. + logk("III\n"); + while (1) { + logk("read ide....\n"); + status = ide_read(i, ATA_REG_STATUS); + logk("read ok\n"); + if ((status & ATA_SR_ERR)) { + err = 1; + break; + } // If Err, Device is not ATA. + if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ)) + break; // Everything is right. + } + + // (IV) Probe for ATAPI Devices: + logk("IV\n"); + if (err != 0) { + unsigned char cl = ide_read(i, ATA_REG_LBA1); + unsigned char ch = ide_read(i, ATA_REG_LBA2); + + if (cl == 0x14 && ch == 0xEB) + type = IDE_ATAPI; + else if (cl == 0x69 && ch == 0x96) + type = IDE_ATAPI; + else + continue; // Unknown Type (may not be a device). + + ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET); + sleep(1); + } + + // (V) Read Identification Space of the Device: + logk("V\n"); + ide_read_buffer(i, ATA_REG_DATA, (unsigned int) ide_buf, 128); + + // (VI) Read Device Parameters: + logk("VI\n"); + ide_devices[count].Reserved = 1; + ide_devices[count].Type = type; + ide_devices[count].Channel = i; + ide_devices[count].Drive = j; + ide_devices[count].Signature = + *((unsigned short *) (ide_buf + ATA_IDENT_DEVICETYPE)); + ide_devices[count].Capabilities = + *((unsigned short *) (ide_buf + ATA_IDENT_CAPABILITIES)); + ide_devices[count].CommandSets = + *((unsigned int *) (ide_buf + ATA_IDENT_COMMANDSETS)); + + // (VII) Get Size: + logk("VII\n"); + if (ide_devices[count].CommandSets & (1 << 26)) + // Device uses 48-Bit Addressing: + ide_devices[count].Size = + *((unsigned int *) (ide_buf + ATA_IDENT_MAX_LBA_EXT)); + else + // Device uses CHS or 28-bit Addressing: + ide_devices[count].Size = + *((unsigned int *) (ide_buf + ATA_IDENT_MAX_LBA)); + + // (VIII) String indicates model of device (like Western Digital HDD and + // SONY DVD-RW...): + logk("VIII\n"); + for (k = 0; k < 40; k += 2) { + ide_devices[count].Model[k] = ide_buf[ATA_IDENT_MODEL + k + 1]; + ide_devices[count].Model[k + 1] = ide_buf[ATA_IDENT_MODEL + k]; + } + ide_devices[count].Model[40] = 0; // Terminate String. + + count++; + } + + // 4- Print Summary: + vdisk vd; + for (int i = 0; i < 4; i++) + if (ide_devices[i].Reserved == 1) { + logk(" %d Found %s Drive %dMB - %s\n", i, + (const char *[]) {"ATA", "ATAPI"}[ide_devices[i].Type], /* Type */ + ide_devices[i].Size / 1024 / 2, /* Size */ + ide_devices[i].Model); + strcpy(vd.DriveName, ide_devices[i].Model); + vd.flag = 1; + vd.Read = Read; + vd.Write = Write; + vd.size = ide_devices[i].Size; + printf("[Disk-(%c)]: Size: %dMB | Name: %s\n", register_vdisk(vd), vd.size, vd.DriveName); + } } unsigned char ide_read(unsigned char channel, unsigned char reg) { @@ -70,6 +191,7 @@ unsigned char ide_read(unsigned char channel, unsigned char reg) { ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN); return result; } + void ide_write(unsigned char channel, unsigned char reg, unsigned char data) { if (reg > 0x07 && reg < 0x0C) ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN); @@ -84,6 +206,7 @@ void ide_write(unsigned char channel, unsigned char reg, unsigned char data) { if (reg > 0x07 && reg < 0x0C) ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN); } + void ide_read_buffer(unsigned char channel, unsigned char reg, unsigned int buffer, unsigned int quads) { /* WARNING: This code contains a serious bug. The inline assembly trashes ES @@ -105,6 +228,7 @@ void ide_read_buffer(unsigned char channel, unsigned char reg, if (reg > 0x07 && reg < 0x0C) ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN); } + unsigned char ide_polling(unsigned char channel, unsigned int advanced_check) { // (I) Delay 400 nanosecond for BSY to be set: // ------------------------------------------------- @@ -119,7 +243,7 @@ unsigned char ide_polling(unsigned char channel, unsigned int advanced_check) { while (a & ATA_SR_BSY) { logk("a=%d\n", a & ATA_SR_BSY); // Wait for BSY to be zero. a = ide_read(channel, ATA_REG_STATUS); - clock_sleep(1); + sleep(1); } logk("II OK\n"); if (advanced_check) { @@ -198,11 +322,11 @@ unsigned char ide_print_error(unsigned int drive, unsigned char err) { } printk( "- [%s %s] %s\n", - (const char *[]){ + (const char *[]) { "Primary", "Secondary"}[ide_devices[drive].Channel], // Use the channel as an // index into the array - (const char *[]){ + (const char *[]) { "Master", "Slave"}[ide_devices[drive].Drive], // Same as above, using the drive ide_devices[drive].Model); @@ -317,26 +441,25 @@ unsigned char ide_ata_access(unsigned char direction, unsigned char drive, ide_write(channel, ATA_REG_COMMAND, cmd); // Send the Command. logk("IV1\n"); if (dma) - if (direction == 0) - ; + if (direction == 0); // DMA Read. - else - ; + else; // DMA Write. else if (direction == 0) { // PIO Read. uint16_t *word_ = edi; for (i = 0; i < numsects; i++) { - logk("read %d\n", i); + // printf("read %d\n", i); if (err = ide_polling(channel, 1)) return err; // Polling, set error and exit if there is. logk("words=%d bus=%d\n", words, bus); - // for (int h = 0; h < words; h++) { - // unsigned short a = io_in16(bus); - // word_[i * words + h] = a; - // } - insl(bus, word_ + i * words, words / 2); + for (int h = 0; h < words; h++) { + unsigned short a = io_in16(bus); + word_[i * words + h] = a; + // printf("%04x ",a); + } + //insl(bus, word_ + i * words, words / 2); } } else { // PIO Write. @@ -353,18 +476,19 @@ unsigned char ide_ata_access(unsigned char direction, unsigned char drive, } } ide_write(channel, ATA_REG_COMMAND, - (char[]){ATA_CMD_CACHE_FLUSH, ATA_CMD_CACHE_FLUSH, - ATA_CMD_CACHE_FLUSH_EXT}[lba_mode]); + (char[]) {ATA_CMD_CACHE_FLUSH, ATA_CMD_CACHE_FLUSH, + ATA_CMD_CACHE_FLUSH_EXT}[lba_mode]); ide_polling(channel, 0); // Polling. } return 0; // Easy, isn't it? } + void ide_wait_irq() { - while (!ide_irq_invoked) - ; + while (!ide_irq_invoked); ide_irq_invoked = 0; } + void ide_irq() { logk("ide irq.\n"); ide_irq_invoked = 1; @@ -403,8 +527,7 @@ unsigned char ide_atapi_read(unsigned char drive, unsigned int lba, ide_write(channel, ATA_REG_HDDEVSEL, slavebit << 4); logk("II\n"); // (III): Delay 400 nanoseconds for select to complete: - for (int i = 0; i < 4000; i++) - ; + for (int i = 0; i < 4000; i++); logk("III\n"); // ------------------------------------------------------------------ logk("IV\n"); @@ -459,11 +582,11 @@ unsigned char ide_atapi_read(unsigned char drive, unsigned int lba, // (XI): Waiting for BSY & DRQ to clear: // ------------------------------------------------------------------ - while (ide_read(channel, ATA_REG_STATUS) & (ATA_SR_BSY | ATA_SR_DRQ)) - ; + while (ide_read(channel, ATA_REG_STATUS) & (ATA_SR_BSY | ATA_SR_DRQ)); return 0; // Easy, ... Isn't it? } + void ide_read_sectors(unsigned char drive, unsigned char numsects, unsigned int lba, unsigned short es, unsigned int edi) { // 1: Check if the drive presents: @@ -491,7 +614,7 @@ void ide_read_sectors(unsigned char drive, unsigned char numsects, package[0] = ide_print_error(drive, err); } } -// package[0] is an entry of an array. It contains the Error Code. + void ide_write_sectors(unsigned char drive, unsigned char numsects, unsigned int lba, unsigned short es, unsigned int edi) { // 1: Check if the drive presents: @@ -575,7 +698,7 @@ void ide_atapi_eject(unsigned char drive) { // (VI): Sending the packet data: // ------------------------------------------------------------------ - asm("rep outsw" ::"c"(6), "d"(bus), + asm("rep outsw"::"c"(6), "d"(bus), "S"(atapi_packet)); // Send Packet Data ide_wait_irq(); // Wait for an IRQ. err = ide_polling(channel, 1); // Polling and get error code. @@ -584,152 +707,4 @@ void ide_atapi_eject(unsigned char drive) { package[0] = ide_print_error(drive, err); // Return; } -} - -void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2, - unsigned int BAR3, unsigned int BAR4) { - int i1, j1, k1; - int flag = 0; - for (i1 = 0; i1 < 255; i1++) { - for (j1 = 0; j1 < 32; j1++) { - for (k1 = 0; k1 < 8; k1++) { - uint32_t p = read_pci(i1, j1, k1, 0x8); - uint16_t *reg = - &p; // reg[0] ---> P & R, reg[1] ---> Sub Class Class Code - uint8_t *codes = - &(reg[1]); // codes[0] --> Sub Class Code codes[1] Class Code - if (codes[1] == 0x1 && codes[0] == 0x1) { - flag = 1; - goto OK; - } - } - } - } - OK: - if (flag == 0) { - return; - } - BAR0 = read_bar_n(i1, j1, k1, 0); - BAR1 = read_bar_n(i1, j1, k1, 1); - BAR2 = read_bar_n(i1, j1, k1, 2); - BAR3 = read_bar_n(i1, j1, k1, 3); - BAR4 = read_bar_n(i1, j1, k1, 4); - int j, k, count = 0; - for (int i = 0; i < 4; i++) { - ide_devices[i].Reserved = 0; - } - // 1- Detect I/O Ports which interface IDE Controller: - channels[ATA_PRIMARY].base = (BAR0 & 0xFFFFFFFC) + 0x1F0 * (!BAR0); - channels[ATA_PRIMARY].ctrl = (BAR1 & 0xFFFFFFFC) + 0x3F6 * (!BAR1); - channels[ATA_SECONDARY].base = (BAR2 & 0xFFFFFFFC) + 0x170 * (!BAR2); - channels[ATA_SECONDARY].ctrl = (BAR3 & 0xFFFFFFFC) + 0x376 * (!BAR3); - channels[ATA_PRIMARY].bmide = (BAR4 & 0xFFFFFFFC) + 0; // Bus Master IDE - channels[ATA_SECONDARY].bmide = (BAR4 & 0xFFFFFFFC) + 8; // Bus Master IDE - // 2- Disable IRQs: - ide_write(ATA_PRIMARY, ATA_REG_CONTROL, 2); - ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 2); - logk("w1\n"); - // 3- Detect ATA-ATAPI Devices: - for (int i = 0; i < 2; i++) - for (j = 0; j < 2; j++) { - unsigned char err = 0, type = IDE_ATA, status; - ide_devices[count].Reserved = 0; // Assuming that no drive here. - - // (I) Select Drive: - ide_write(i, ATA_REG_HDDEVSEL, 0xA0 | (j << 4)); // Select Drive. - clock_sleep(1); // Wait 1ms for drive select to work. - logk("I\n"); - // (II) Send ATA Identify Command: - ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY); - clock_sleep(1); // This function should be implemented in your OS. which waits - // for 1 ms. it is based on System Timer Device Driver. - logk("II\n"); - // (III) Polling: - if (ide_read(i, ATA_REG_STATUS) == 0) - continue; // If Status = 0, No Device. - logk("III\n"); - while (1) { - logk("read ide....\n"); - status = ide_read(i, ATA_REG_STATUS); - logk("read ok\n"); - if ((status & ATA_SR_ERR)) { - err = 1; - break; - } // If Err, Device is not ATA. - if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ)) - break; // Everything is right. - } - - // (IV) Probe for ATAPI Devices: - logk("IV\n"); - if (err != 0) { - unsigned char cl = ide_read(i, ATA_REG_LBA1); - unsigned char ch = ide_read(i, ATA_REG_LBA2); - - if (cl == 0x14 && ch == 0xEB) - type = IDE_ATAPI; - else if (cl == 0x69 && ch == 0x96) - type = IDE_ATAPI; - else - continue; // Unknown Type (may not be a device). - - ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET); - clock_sleep(1); - } - - // (V) Read Identification Space of the Device: - logk("V\n"); - ide_read_buffer(i, ATA_REG_DATA, (unsigned int)ide_buf, 128); - - // (VI) Read Device Parameters: - logk("VI\n"); - ide_devices[count].Reserved = 1; - ide_devices[count].Type = type; - ide_devices[count].Channel = i; - ide_devices[count].Drive = j; - ide_devices[count].Signature = - *((unsigned short *)(ide_buf + ATA_IDENT_DEVICETYPE)); - ide_devices[count].Capabilities = - *((unsigned short *)(ide_buf + ATA_IDENT_CAPABILITIES)); - ide_devices[count].CommandSets = - *((unsigned int *)(ide_buf + ATA_IDENT_COMMANDSETS)); - - // (VII) Get Size: - logk("VII\n"); - if (ide_devices[count].CommandSets & (1 << 26)) - // Device uses 48-Bit Addressing: - ide_devices[count].Size = - *((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA_EXT)); - else - // Device uses CHS or 28-bit Addressing: - ide_devices[count].Size = - *((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA)); - - // (VIII) String indicates model of device (like Western Digital HDD and - // SONY DVD-RW...): - logk("VIII\n"); - for (k = 0; k < 40; k += 2) { - ide_devices[count].Model[k] = ide_buf[ATA_IDENT_MODEL + k + 1]; - ide_devices[count].Model[k + 1] = ide_buf[ATA_IDENT_MODEL + k]; - } - ide_devices[count].Model[40] = 0; // Terminate String. - - count++; - } - - // 4- Print Summary: - vdisk vd; - for (int i = 0; i < 4; i++) - if (ide_devices[i].Reserved == 1) { - logk(" %d Found %s Drive %dMB - %s\n", i, - (const char *[]){"ATA", "ATAPI"}[ide_devices[i].Type], /* Type */ - ide_devices[i].Size / 1024 / 2, /* Size */ - ide_devices[i].Model); - strcpy(vd.DriveName, ide_devices[i].Model); - vd.flag = 1; - vd.Read = Read; - vd.Write = Write; - vd.size = ide_devices[i].Size; - printf("[Disk (%c)]: Size: %dMB Name: %s\n",register_vdisk(vd),vd.size,vd.DriveName); - } } \ No newline at end of file diff --git a/driver/keyboard.c b/driver/keyboard.c index 2f68725..c81a037 100644 --- a/driver/keyboard.c +++ b/driver/keyboard.c @@ -90,7 +90,7 @@ unsigned char shift_keyboard_map[128] = static void default_handle(uint32_t key,int release,char c){ if(!release) { - if(c == -1) { + if(key == 42) { key_status->is_shift = 1; return 0; } @@ -106,7 +106,7 @@ static void default_handle(uint32_t key,int release,char c){ queue_push(key_char_queue,(char)c); } else { - if(c == -1){ + if(key == -86){ key_status->is_shift = 0; } @@ -125,6 +125,7 @@ void init_keyboard(){ head_listener = (struct key_listener*) kmalloc(sizeof(struct key_listener)); head_listener->func = default_handle; head_listener->lid = 0; + head_listener->next = NULL; register_interrupt_handler(0x21,handle_keyboard_input); } diff --git a/driver/vdisk.c b/driver/vdisk.c index af0ff4b..0e17c4d 100644 --- a/driver/vdisk.c +++ b/driver/vdisk.c @@ -10,30 +10,27 @@ int getReadyDisk(); -vdisk vdisk_ctl[10]; +vdisk vdisk_ctl[26]; int init_vdisk() { - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 26; i++) { vdisk_ctl[i].flag = 0; // 设置为未使用 } - printf("[\035kernel\036]: VDisk driver load success!\n"); - return 0; } int register_vdisk(vdisk vd) { - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 26; i++) { if (!vdisk_ctl[i].flag) { vdisk_ctl[i] = vd; // 找到了! return i + ('A'); // 注册成功,返回drive } } - printf("[vdisk]not found\n"); + printk("[vdisk]not found\n"); return 0; // 注册失败 } - int logout_vdisk(char drive) { int indx = drive - ('A'); - if (indx > 10) { + if (indx > 26) { return 0; // 失败 } if (vdisk_ctl[indx].flag) { @@ -43,17 +40,15 @@ int logout_vdisk(char drive) { return 0; // 失败 } } - int rw_vdisk(char drive, unsigned int lba, unsigned char *buffer, unsigned int number, int read) { int indx = drive - ('A'); - if (indx > 10) { + if (indx > 26) { return 0; // 失败 } if (vdisk_ctl[indx].flag) { if (read) { vdisk_ctl[indx].Read(drive, buffer, number, lba); - //for(;;); } else { vdisk_ctl[indx].Write(drive, buffer, number, lba); } @@ -62,10 +57,10 @@ int rw_vdisk(char drive, unsigned int lba, unsigned char *buffer, return 0; // 失败 } } - -int have_vdisk(char drive) { +bool have_vdisk(char drive) { int indx = drive - 'A'; - if (indx > 10) { + // printk("drive=%c\n",drive); + if (indx > 26) { return 0; // 失败 } if (vdisk_ctl[indx].flag) { @@ -74,63 +69,23 @@ int have_vdisk(char drive) { return 0; // 失败 } } - -void Disk_Read(unsigned int lba, unsigned int number, void *buffer, - char drive) { - if (have_vdisk(drive)) { - for (int i = 0; i < number; i += SECTORS_ONCE) { - int sectors = - ((number - i) >= SECTORS_ONCE) ? SECTORS_ONCE : (number - i); - rw_vdisk(drive, lba + i, buffer + i * 512, sectors, 1); - } - } -} - -int disk_Size(char drive) { - unsigned char drive1 = drive; - if (have_vdisk(drive1)) { - int indx = drive1 - 'A'; - return vdisk_ctl[indx].size; - } else { - print("Disk Not Ready.\n"); - return 0; - } - - return 0; -} - -int DiskReady(char drive) { return have_vdisk(drive); } - -int getReadyDisk() { return 0; } - -void Disk_Write(unsigned int lba, unsigned int number, void *buffer, - char drive) { - if (have_vdisk(drive)) { - for (int i = 0; i < number; i += SECTORS_ONCE) { - int sectors = - ((number - i) >= SECTORS_ONCE) ? SECTORS_ONCE : (number - i); - rw_vdisk(drive, lba + i, buffer + i * 512, sectors, 0); - } - } -} +// 基于vdisk的通用读写 static unsigned char *drive_name[16] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; static struct FIFO8 drive_fifo[16]; static unsigned char drive_buf[16][256]; - bool SetDrive(unsigned char *name) { for (int i = 0; i != 16; i++) { if (drive_name[i] == NULL) { drive_name[i] = name; fifo8_init(&drive_fifo[i], 256, drive_buf[i]); - return 1; + return true; } } - return 0; + return false; } - unsigned int GetDriveCode(unsigned char *name) { for (int i = 0; i != 16; i++) { if (strcmp((char *)drive_name[i], (char *)name) == 0) { @@ -141,24 +96,48 @@ unsigned int GetDriveCode(unsigned char *name) { } bool DriveSemaphoreTake(unsigned int drive_code) { - if (drive_code >= 16) { - return 1; - } - fifo8_put(&drive_fifo[drive_code], get_current()->pid); - // printk("FIFO: %d PUT: %d STATUS: %d\n", drive_code, Get_Tid(current_task()), - // fifo8_status(&drive_fifo[drive_code])); - while (drive_buf[drive_code][drive_fifo[drive_code].q] != - get_current()->pid) { - // printk("Waiting....\n"); - } - return 1; + return true; } void DriveSemaphoreGive(unsigned int drive_code) { - if (drive_code >= 16) { - return; - } - if (drive_buf[drive_code][drive_fifo[drive_code].q] != get_current()->pid) { - return; - } - fifo8_get(&drive_fifo[drive_code]); + return; +} + +void Disk_Read(unsigned int lba, unsigned int number, void *buffer, + char drive) { + if (have_vdisk(drive)) { + if (DriveSemaphoreTake(GetDriveCode((unsigned char *)"DISK_DRIVE"))) { + for (int i = 0; i < number; i += SECTORS_ONCE) { + int sectors = ((number - i) >= SECTORS_ONCE) ? SECTORS_ONCE : (number - i); + rw_vdisk(drive, lba + i, buffer + i * 512, sectors, 1); + } + DriveSemaphoreGive(GetDriveCode((unsigned char *)"DISK_DRIVE")); + } + } +} +unsigned int disk_Size(char drive) { + unsigned char drive1 = drive; + if (have_vdisk(drive1)) { + int indx = drive1 - 'A'; + return vdisk_ctl[indx].size; + } else { + return 0; + } + + return 0; +} +bool DiskReady(char drive) { return have_vdisk(drive); } +int getReadyDisk() { return 0; } +void Disk_Write(unsigned int lba, unsigned int number, void *buffer, + char drive) { +// printk("%d\n",lba); + if (have_vdisk(drive)) { + if (DriveSemaphoreTake(GetDriveCode((unsigned char *)"DISK_DRIVE"))) { + // printk("*buffer(%d %d) = %02x\n",lba,number,*(unsigned char *)buffer); + for (int i = 0; i < number; i += SECTORS_ONCE) { + int sectors = ((number - i) >= SECTORS_ONCE) ? SECTORS_ONCE : (number - i); + rw_vdisk(drive, lba + i, buffer + i * 512, sectors, 0); + } + DriveSemaphoreGive(GetDriveCode((unsigned char *)"DISK_DRIVE")); + } + } } diff --git a/fs/fat.c b/fs/fat.c new file mode 100644 index 0000000..db17f9b --- /dev/null +++ b/fs/fat.c @@ -0,0 +1,1302 @@ +#include "../include/fat.h" +#include "../include/vdisk.h" +#include "../include/memory.h" +#include "../include/vfs.h" +#include "../include/printf.h" +#include "../include/cmos.h" + +#define get_dm(vfs) ((fat_cache *)(vfs->cache))->dm +#define get_now_dir(vfs) ((fat_cache *)(vfs->cache))->dir +#define get_clustno(high, low) (high << 16) | (low & 0xffff) +#define clustno_end(type) 0xfffffff & ((((1 << (type - 1)) - 1) << 1) + 1) + +static inline int get_fat_date(unsigned short year, unsigned short month, + unsigned short day) { + year -= 1980; + unsigned short date = 0; + date |= (year & 0x7f) << 9; + date |= (month & 0x0f) << 5; + date |= (day & 0x1f); + return date; +} +static inline int get_fat_time(unsigned short hour, unsigned short minute) { + unsigned short time = 0; + time |= (hour & 0x1f) << 11; + time |= (minute & 0x3f) << 5; + return time; +} +void read_fat(unsigned char *img, int *fat, unsigned char *ff, int max, + int type) { + if (type == 12) { + for (int i = 0, j = 0; i < max; i += 2) { + fat[i + 0] = (img[j + 0] | img[j + 1] << 8) & 0xfff; + fat[i + 1] = (img[j + 1] >> 4 | img[j + 2] << 4) & 0xfff; + j += 3; + } + // 保留簇 + ff[0] = true; + ff[1] = true; + for (int i = 1; i < max; i++) { + if (fat[i] > 0 && fat[i] < 0xff0) { + ff[fat[i]] = true; + } else if (fat[i] >= 0xff0 && fat[i] <= 0xfff) { + ff[i + 1] = true; + } + } + } else if (type == 16) { + unsigned short *p = (unsigned short *)img; + for (int i = 0; i != max; i++) { + fat[i] = p[i]; + } + ff[0] = true; + ff[1] = true; + for (int i = 1; i < max; i++) { + if (fat[i] > 0 && fat[i] < 0xfff0) { + ff[fat[i]] = true; + } else if (fat[i] >= 0xfff0 && fat[i] <= 0xffff) { + ff[i + 1] = true; + } + } + } else if (type == 32) { + unsigned int *p = (unsigned int *)img; + for (int i = 0; i != max; i++) { + fat[i] = p[i]; + } + ff[0] = true; + ff[1] = true; + for (int i = 1; i < max; i++) { + if (fat[i] > 0 && fat[i] < 0xffffff0) { + ff[fat[i]] = true; + } else if (fat[i] >= 0xffffff0 && fat[i] <= 0xfffffff) { + ff[i + 1] = true; + } + } + } + return; +} +int get_directory_max(struct FAT_FILEINFO *directory, vfs_t *vfs) { + if (directory == get_dm(vfs).root_directory) { + return get_dm(vfs).RootMaxFiles; + } + for (int i = 1; FindForCount(i, get_dm(vfs).directory_list) != NULL; i++) { + struct List *l = FindForCount(i, get_dm(vfs).directory_list); + if ((struct FAT_FILEINFO *)l->val == directory) { + return (int)FindForCount(i, get_dm(vfs).directory_max_list)->val; + } + } +} +void file_loadfile(int clustno, int size, char *buf, int *fat, vfs_t *vfs) { + if (!size) { + return; + } + int s = + ((size - 1) / get_dm(vfs).ClustnoBytes + 1) * get_dm(vfs).ClustnoBytes; + void *img = kmalloc(s); + int flag = 0, a, num = 0, sec_start = 0; + for (int i = 0; i != (size - 1) / get_dm(vfs).ClustnoBytes + 1; i++) { + uint32_t sec = (get_dm(vfs).FileDataAddress + + (clustno - 2) * get_dm(vfs).ClustnoBytes) / + get_dm(vfs).SectorBytes; + if (!flag) { + a = sec; + num = 1; + } else { + if (a + num == sec) { + num++; + } else { + Disk_Read(a, num * get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes, + img + sec_start * get_dm(vfs).ClustnoBytes, vfs->disk_number); + sec_start += num; + a = sec; + num = 1; + clustno = fat[clustno]; + continue; + } + } + // Disk_Read(sec, get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes, + // img + i * get_dm(vfs).ClustnoBytes, vfs->disk_number); + flag = 1; + clustno = fat[clustno]; + } + if (num) { + Disk_Read(a, num * get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes, + img + sec_start * get_dm(vfs).ClustnoBytes, vfs->disk_number); + } + memcpy((void *)buf, img, size); + kfree(img); + return; +} +void file_savefile(int clustno, int size, char *buf, int *fat, + unsigned char *ff, vfs_t *vfs) { + uint32_t clustall = 0; + int tmp = clustno; + int end = clustno_end(get_dm(vfs).type); + while (fat[clustno] != end) { // 计算文件占多少Fat项 Fat项 = 大小 / 簇大小 + 1 + clustno = fat[clustno]; + clustall++; + } + int old_clustno = clustno; + clustno = tmp; + int alloc_size; + if (size > + (clustall + 1) * + get_dm(vfs).ClustnoBytes) { // 新大小 > (旧大小 / 簇大小 + 1) * 簇大小 + // 请求内存大小 = (新大小 / 簇大小 + 1) * 簇大小 + alloc_size = + ((size - 1) / get_dm(vfs).ClustnoBytes + 1) * get_dm(vfs).ClustnoBytes; + // 分配Fat(这里需要在写盘前分配) + for (int size1 = size; size1 > ((clustall + 1) * get_dm(vfs).ClustnoBytes); + size1 -= get_dm(vfs).ClustnoBytes) { + for (int i = 0; i != get_dm(vfs).FatMaxTerms; i++) { + if (!ff[i]) { + fat[old_clustno] = i; + old_clustno = i; + ff[i] = true; + break; + } + } + } + fat[old_clustno] = end; // 结尾Fat + ff[old_clustno] = true; + } else if (size <= + (clustall + 1) * + get_dm(vfs).ClustnoBytes) { // 新大小 <= (旧大小 / 簇大小 + // + 1) * 簇大小 + // 请求内存大小 = (旧大小 / 簇大小 + 1) * 簇大小 + alloc_size = (clustall + 1) * get_dm(vfs).ClustnoBytes; + // 这里不分配Fat的原因是要清空更改后多余的数据 + } + void *img = kmalloc(alloc_size); + memclean((char *)img, alloc_size); + memcpy(img, buf, size); // 把要写入的数据复制到新请求的内存地址 + // for (int i = 0; i != (alloc_size / get_dm(vfs).ClustnoBytes); i++) { + // uint32_t sec = (get_dm(vfs).FileDataAddress + + // (clustno - 2) * get_dm(vfs).ClustnoBytes) / + // get_dm(vfs).SectorBytes; + // Disk_Write(sec, get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes, + // img + i * get_dm(vfs).ClustnoBytes, vfs->disk_number); + // clustno = fat[clustno]; + // } + int flag = 0, a, num = 0, sec_start = 0; + for (int i = 0; i != (alloc_size / get_dm(vfs).ClustnoBytes); i++) { + uint32_t sec = (get_dm(vfs).FileDataAddress + + (clustno - 2) * get_dm(vfs).ClustnoBytes) / + get_dm(vfs).SectorBytes; + if (!flag) { + a = sec; + num = 1; + } else { + if (a + num == sec) { + num++; + } else { + Disk_Write(a, num * get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes, + img + sec_start * get_dm(vfs).ClustnoBytes, + vfs->disk_number); + sec_start += num; + a = sec; + num = 1; + clustno = fat[clustno]; + continue; + } + } + // Disk_Read(sec, get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes, + // img + i * get_dm(vfs).ClustnoBytes, vfs->disk_number); + flag = 1; + clustno = fat[clustno]; + } + if (num) { + Disk_Write(a, num * get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes, + img + sec_start * get_dm(vfs).ClustnoBytes, vfs->disk_number); + } + kfree(img); + if (size < + clustall * + get_dm(vfs).ClustnoBytes) { // 新大小 < (旧大小 / 簇大小) * 簇大小 + // 分配Fat(中间情况没必要分配) + int i = old_clustno; + for (int size1 = clustall * get_dm(vfs).ClustnoBytes; size1 > size; + size1 -= get_dm(vfs).ClustnoBytes) { + fat[i] = 0; + ff[i] = false; + for (int j = 0; j != get_dm(vfs).FatMaxTerms; j++) { + if (fat[j] == i) { + i = j; + } + } + } + old_clustno = i; + fat[old_clustno] = end; + ff[old_clustno] = true; + } + file_savefat(fat, 0, get_dm(vfs).FatMaxTerms, vfs); +} +void file_saveinfo(struct FAT_FILEINFO *directory, vfs_t *vfs) { + if (directory == get_dm(vfs).root_directory) { + Disk_Write(get_dm(vfs).RootDictAddress / get_dm(vfs).SectorBytes, + get_dm(vfs).RootMaxFiles * 32 / get_dm(vfs).SectorBytes, + (void *)directory, vfs->disk_number); + } else { + for (int i = 1; FindForCount(i, get_dm(vfs).directory_list) != NULL; i++) { + struct List *list = FindForCount(i, get_dm(vfs).directory_list); + if (list->val == directory) { + list = FindForCount(i, get_dm(vfs).directory_clustno_list); + int k = (int)FindForCount(i, get_dm(vfs).directory_max_list)->val * 32 / + get_dm(vfs).ClustnoBytes; + for (int j = list->val, l = 0; l != k; l++) { + Disk_Write((get_dm(vfs).FileDataAddress + + (j - 2) * get_dm(vfs).ClustnoBytes) / + get_dm(vfs).SectorBytes, + get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes, + (char *)directory + l * get_dm(vfs).SectorBytes, + vfs->disk_number); + j = get_dm(vfs).fat[j]; + } + break; + } + } + } +} +void file_savefat(int *fat, int clustno, int length, vfs_t *vfs) { + unsigned char *img = get_dm(vfs).ADR_DISKIMG + get_dm(vfs).Fat1Address; + int size, sec; + if (get_dm(vfs).type == 12) { + for (int i = 0; i <= length; i++) { + if ((clustno + i) % 2 == 0) { + img[(clustno + i) * 3 / 2 + 0] = fat[clustno + i] & 0xff; + img[(clustno + i) * 3 / 2 + 1] = + (fat[clustno + i] >> 8 | (img[(clustno + i) * 3 / 2 + 1] & 0xf0)) & + 0xff; + } else if ((clustno + i) % 2 != 0) { + img[(clustno + i - 1) * 3 / 2 + 1] = + ((img[(clustno + i - 1) * 3 / 2 + 1] & 0x0f) | fat[clustno + i] + << 4) & + 0xff; + img[(clustno + i - 1) * 3 / 2 + 2] = (fat[clustno + i] >> 4) & 0xff; + } + } + size = length * 3 / 2 - 1; + sec = clustno * 3 / 2; + } else if (get_dm(vfs).type == 16) { + for (int i = 0; i <= length; i++) { + img[(clustno + i) * 2 + 0] = fat[clustno + i] & 0xff; + img[(clustno + i) * 2 + 1] = (fat[clustno + i] >> 8) & 0xff; + } + size = length * 2 - 1; + sec = clustno * 2; + } else if (get_dm(vfs).type == 32) { + for (int i = 0; i <= length; i++) { + img[(clustno + i) * 4 + 0] = fat[clustno + i] & 0xff; + img[(clustno + i) * 4 + 1] = (fat[clustno + i] >> 8) & 0xff; + img[(clustno + i) * 4 + 2] = (fat[clustno + i] >> 16) & 0xff; + img[(clustno + i) * 4 + 3] = fat[clustno + i] >> 24; + } + size = length * 4 - 1; + sec = clustno * 4; + } + Disk_Write((get_dm(vfs).Fat1Address + sec) / get_dm(vfs).SectorBytes, + size / get_dm(vfs).SectorBytes + 1, + get_dm(vfs).ADR_DISKIMG + get_dm(vfs).Fat1Address, + vfs->disk_number); + Disk_Write((get_dm(vfs).Fat2Address + sec) / get_dm(vfs).SectorBytes, + size / get_dm(vfs).SectorBytes + 1, + get_dm(vfs).ADR_DISKIMG + get_dm(vfs).Fat2Address, + vfs->disk_number); +} +struct FAT_FILEINFO *file_search(char *name, struct FAT_FILEINFO *finfo, + int max) { + int i, j; + char s[12]; + for (j = 0; j < 11; j++) { + s[j] = ' '; + } + j = 0; + for (i = 0; name[i] != 0; i++) { + if (j >= 11) { + return 0; /*没有找到*/ + } + if (name[i] == '.' && j <= 8) { + j = 8; + } else { + s[j] = name[i]; + if ('a' <= s[j] && s[j] <= 'z') { + /*将小写字母转换为大写字母*/ + s[j] -= 0x20; + } + j++; + } + } + for (i = 0; i < max;) { + if (finfo[i].name[0] == 0x00) { + break; + } + if ((finfo[i].type & 0x18) == 0) { + for (j = 0; j < 11; j++) { + if (finfo[i].name[j] != s[j]) { + goto next; + } + } + return finfo + i; /*找到文件*/ + } + next: + i++; + } + return 0; /*没有找到*/ +} +struct FAT_FILEINFO *dict_search(char *name, struct FAT_FILEINFO *finfo, + int max) { + int i, j; + char s[12]; + for (j = 0; j < 11; j++) { + s[j] = ' '; + } + j = 0; + for (i = 0; name[i] != 0; i++) { + if (j >= 11) { + return 0; /*没有找到*/ + } else { + s[j] = name[i]; + if ('a' <= s[j] && s[j] <= 'z') { + /*将小写字母转换为大写字母*/ + s[j] -= 0x20; + } + j++; + } + } + for (i = 0; i < max;) { + if (finfo[i].name[0] == 0x00) { + break; + } + if (finfo[i].type == 0x10) { + for (j = 0; j < 11; j++) { + if (finfo[i].name[j] != s[j]) { + goto next; + } + } + return finfo + i; /* 找到文件 */ + } + next: + i++; + } + return 0; /*没有找到*/ +} +struct FAT_FILEINFO *Get_File_Address(char *path1, vfs_t *vfs) { + // TODO: Modifly it + struct FAT_FILEINFO *bmpDict = get_now_dir(vfs); + int drive_number = vfs->disk_number; + char *path = (char *)kmalloc(strlen(path1) + 1); + char *bmp = path; + strcpy(path, path1); + strtoupper(path); + if (strncmp("/", path, 1) == 0) { + path += 1; + bmpDict = get_dm(vfs).root_directory; + } + if (path[0] == '\\' || path[0] == '/') { + // 跳过反斜杠和正斜杠 + for (int i = 0; i < strlen(path); i++) { + if (path[i] != '\\' && path[i] != '/') { + path += i; + break; + } + } + } + char *temp_name = (char *)kmalloc(128); + memclean(temp_name,128); + struct FAT_FILEINFO *finfo = get_dm(vfs).root_directory; + int i = 0; + while (1) { + int j; + for (j = 0; i < strlen(path); i++, j++) { + if (path[i] == '\\' || path[i] == '/') { + temp_name[j] = '\0'; + i++; + break; + } + temp_name[j] = path[i]; + } + finfo = dict_search(temp_name, bmpDict, get_directory_max(bmpDict, vfs)); + + if (finfo == 0) { + if (path[i] != '\0') { + kfree((void *)temp_name); + kfree((void *)bmp); + return 0; + } + finfo = file_search(temp_name, bmpDict, get_directory_max(bmpDict, vfs)); + if (finfo == 0) { + kfree((void *)temp_name); + kfree((void *)bmp); + return 0; + } else { + goto END; + } + } else { + if (get_clustno(finfo->clustno_high, finfo->clustno_low) != 0) { + for (int count = 1; + FindForCount(count, get_dm(vfs).directory_clustno_list) != NULL; + count++) { + struct List *list = + FindForCount(count, get_dm(vfs).directory_clustno_list); + if (get_clustno(finfo->clustno_high, finfo->clustno_low) == + list->val) { + list = FindForCount(count, get_dm(vfs).directory_list); + bmpDict = (struct FAT_FILEINFO *)list->val; + break; + } + } + } else { + bmpDict = get_dm(vfs).root_directory; + } + memclean(temp_name, 128); + } + } + END: + kfree((void *)temp_name); + kfree((void *)bmp); + return finfo; +} +struct FAT_FILEINFO *Get_dictaddr(char *path1, vfs_t *vfs) { + // TODO: Modifly it + struct FAT_FILEINFO *bmpDict = get_now_dir(vfs); + int drive_number = vfs->disk_number; + char *path = (char *)kmalloc(strlen(path1) + 1); + char *bmp = path; + strcpy(path, path1); + strtoupper(path); + if (strncmp("/", path, 1) == 0) { + path += 1; + bmpDict = get_dm(vfs).root_directory; + } + if (path[0] == '\\' || path[0] == '/') { + // 跳过反斜杠和正斜杠 + for (int i = 0; i < strlen(path); i++) { + if (path[i] != '\\' && path[i] != '/') { + path += i; + break; + } + } + } + char *temp_name = (char *)kmalloc(128); + struct FAT_FILEINFO *finfo; + int i = 0; + while (1) { + int j; + for (j = 0; i < strlen(path); i++, j++) { + if (path[i] == '\\' || path[i] == '/') { + temp_name[j] = '\0'; + i++; + break; + } + temp_name[j] = path[i]; + } + finfo = dict_search(temp_name, bmpDict, get_directory_max(bmpDict, vfs)); + + if (finfo == 0) { + if (path[i] != 0) { + bmpDict = NULL; + } + goto END; + } else { + if (get_clustno(finfo->clustno_high, finfo->clustno_low) != 0) { + for (int count = 1; + FindForCount(count, get_dm(vfs).directory_clustno_list) != NULL; + count++) { + struct List *list = + FindForCount(count, get_dm(vfs).directory_clustno_list); + if (get_clustno(finfo->clustno_high, finfo->clustno_low) == + list->val) { + list = FindForCount(count, get_dm(vfs).directory_list); + bmpDict = (struct FAT_FILEINFO *)list->val; + break; + } + } + } else { + bmpDict = get_dm(vfs).root_directory; + } + memclean(temp_name, 128); + if (path[i] == '\0') { + goto END; + } + } + } + END: + kfree((void *)temp_name); + kfree(((void *)bmp)); + return bmpDict; +} +int mkdir(char *dictname, int last_clust, vfs_t *vfs) { + /* + dictname:目录名 + last_clust:上一级目录的簇号 + */ + int r = mkfile(dictname, vfs); + if (!r) + return 0; + // 三个目录项(模板) + static struct FAT_FILEINFO model[3]; + // .目录项,指向自己 + // ..目录项,指向上一级目录 + // 空目录项(为mkfile函数提供指引) + model[0].reserve = 0; + model[1].reserve = 0; + model[2].reserve = 0; + memcpy(model[2].name, "NULL ", 11); + model[2].type = 0x20; // 文件的type属性是0x20 + // 将size date time这类属性全部设置为0 + model[2].size = 0; + model[2].update_date = + get_fat_date(get_year(), get_mon(), get_day_of_month()); + model[2].update_time = get_fat_time(get_hour(), get_min()); + for (int i = 0; i != get_dm(vfs).FatMaxTerms; i++) { + if (!get_dm(vfs).fat[i]) { + model[2].clustno_low = i; + int end = clustno_end(get_dm(vfs).type); + get_dm(vfs).fat[i] = end; + get_dm(vfs).FatClustnoFlags[i] = true; + break; + } + } + model[0].name[0] = '.'; + for (int i = 1; i != 8; i++) { + model[0].name[i] = ' '; + } + for (int i = 0; i != 3; i++) { + model[0].ext[i] = ' '; + } + struct FAT_FILEINFO *finfo1 = Get_File_Address(dictname, vfs); + model[0].type = 0x10; + model[0].clustno_low = finfo1->clustno_low; // 指向自己 + model[0].clustno_high = finfo1->clustno_high; + model[0].size = 0; + model[0].update_date = + get_fat_date(get_year(), get_mon(), get_day_of_month()); + model[0].update_time = get_fat_time(get_hour(), get_min()); + model[1].name[0] = '.'; + model[1].name[1] = '.'; + for (int i = 2; i != 8; i++) { + model[1].name[i] = ' '; + } + for (int i = 0; i != 3; i++) { + model[1].ext[i] = ' '; + } + model[1].clustno_low = last_clust; + model[1].size = 0; + model[1].update_date = + get_fat_date(get_year(), get_mon(), get_day_of_month()); + model[1].update_time = get_fat_time(get_hour(), get_min()); + model[1].type = 0x10; + + Fat_WriteFile(vfs, dictname, (char *)&model[0], 32 * 3); + struct FAT_FILEINFO *finfo = Get_File_Address(dictname, vfs); + + finfo->type = 0x10; // 是目录(文件夹的type属性是0x10) + finfo->size = 0; + int drive_number = vfs->disk_number; + AddVal(get_clustno(finfo->clustno_high, finfo->clustno_low), + get_dm(vfs).directory_clustno_list); + if (last_clust == 0) { + file_saveinfo(get_dm(vfs).root_directory, vfs); + } else { + for (int i = 1; FindForCount(i, get_dm(vfs).directory_clustno_list) != NULL; + i++) { + struct List *list = FindForCount(i, get_dm(vfs).directory_clustno_list); + if (list->val == last_clust) { + list = FindForCount(i, get_dm(vfs).directory_list); + struct FAT_FILEINFO *d_finfo = (struct FAT_FILEINFO *)list->val; + file_saveinfo(d_finfo, vfs); + } + } + } + file_savefat(get_dm(vfs).fat, + get_clustno(model[2].clustno_high, model[2].clustno_low), 1, + vfs); + + void *directory_alloc = kmalloc(get_dm(vfs).ClustnoBytes); + Disk_Read((get_dm(vfs).FileDataAddress + + (get_clustno(finfo->clustno_high, finfo->clustno_low) - 2) * + get_dm(vfs).ClustnoBytes) / + get_dm(vfs).SectorBytes, + get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes, directory_alloc, + vfs->disk_number); + + AddVal(directory_alloc, get_dm(vfs).directory_list); + AddVal(get_dm(vfs).ClustnoBytes / 32, get_dm(vfs).directory_max_list); + + return 1; +} + +struct FAT_FILEINFO *clust_sech(int clustno, struct FAT_FILEINFO *finfo, + int max) { + // 通过簇号找到文件信息 + int i, j; + j = 0; + for (i = 0; i < max; i++) { + if (finfo[i].clustno_low == clustno) { + return finfo + i; + } + } + return 0; /*没找到*/ +} +int del(char *cmdline, vfs_t *vfs) { + // 删除某个文件 + char *name = cmdline; + int i; + struct FAT_FILEINFO *finfo; + finfo = Get_File_Address(name, vfs); + if (finfo == 0 || finfo->type == 0x01 || finfo->type == 0x04) { + return 0; + } + file_savefile(get_clustno(finfo->clustno_high, finfo->clustno_low), 0, NULL, + get_dm(vfs).fat, get_dm(vfs).FatClustnoFlags, vfs); + finfo->name[0] = 0xe5; + get_dm(vfs).fat[get_clustno(finfo->clustno_high, finfo->clustno_low)] = 0; + get_dm(vfs) + .FatClustnoFlags[get_clustno(finfo->clustno_high, finfo->clustno_low)] = + false; + file_saveinfo(Get_dictaddr(name, vfs), vfs); + file_savefat(get_dm(vfs).fat, + get_clustno(finfo->clustno_high, finfo->clustno_low), 1, vfs); + return 1; +} +int deldir(char *path, vfs_t *vfs) { + struct FAT_FILEINFO *finfo = Get_dictaddr(path, vfs); + if (finfo == Get_dictaddr(".", vfs)) { + return 0; + } + struct FAT_FILEINFO *f = get_now_dir(vfs); + get_now_dir(vfs) = finfo; + for (int i = 2; finfo[i].name[0] != '\0'; i++) { + if (finfo[i].type == 0x10 && finfo[i].name[0] != 0xe5) { + char s[30]; + int j = 0; + for (; finfo[i].name[j] != ' '; j++) { + s[j] = finfo[i].name[j]; + } + s[j] = '\0'; + // printk("(CALL)DEL DIR:%s\n", s); + if (deldir(s, vfs) == -1) { + return 0; + } + // return -1; + } + } + for (int i = 2; finfo[i].name[0] != '\0'; i++) { + if (finfo[i].name[0] != 0xe5 && finfo[i].type != 0x10) { + char s[30]; + int p = 0; + for (int j = 0; finfo[i].name[j] != ' '; j++, p++) { + s[p] = finfo[i].name[j]; + } + if (finfo[i].ext[0] != ' ') { + s[p++] = '.'; + for (int j = 0; finfo[i].ext[j] != ' ' || j != 3; j++, p++) { + s[p] = finfo[i].ext[j]; + } + } + s[p] = '\0'; + // printk("(IN)DEL FILE:%s\n", s); + if (del(s, vfs) == -1) { + return 0; + } + } + } + get_now_dir(vfs) = f; + // printk("(IN)DEL SELF\n"); + struct FAT_FILEINFO *root_finfo; + if (finfo[1].clustno_low == 0) { + root_finfo = get_dm(vfs).root_directory; + } else { + for (int i = 1; FindForCount(i, get_dm(vfs).directory_clustno_list) != NULL; + i++) { + if (FindForCount(i, get_dm(vfs).directory_clustno_list)->val == + finfo[1].clustno_low) { + root_finfo = + (struct FAT_FILEINFO *)FindForCount(i, get_dm(vfs).directory_list) + ->val; + // printk("FIND ROOT %08x\n", root_finfo); + } + } + } + for (int i = 0; root_finfo[i].name[0] != '\0'; i++) { + // printk("ROOT FILE:%s\n", root_finfo[i].name); + if (root_finfo[i].clustno_low == finfo[0].clustno_low) { + root_finfo[i].name[0] = 0xe5; + break; + } + } + get_dm(vfs).fat[get_clustno(finfo->clustno_high, finfo->clustno_low)] = 0; + get_dm(vfs) + .FatClustnoFlags[get_clustno(finfo->clustno_high, finfo->clustno_low)] = + false; + file_saveinfo(Get_dictaddr(path, vfs), vfs); + file_savefat(get_dm(vfs).fat, + get_clustno(finfo->clustno_high, finfo->clustno_low), 1, vfs); + return 1; +} +int mkfile(char *name, vfs_t *vfs) { +// logk("mkfile : %s\n", name); + char s[12]; + int i, j; + struct FAT_FILEINFO *finfo = Get_dictaddr(name, vfs); + // logk("finfo = %08x\n", finfo); + if (finfo == NULL) { + return 0; + } + int max = get_directory_max(finfo, vfs); + + char *path = name; + for (i = strlen(name); i >= 0; i--) { + if (name[i] == '/' || name[i] == '\\') { + name += i + 1; + break; + } + } + + for (j = 0; j != 12; j++) { + s[j] = ' '; + } + j = 0; + for (i = 0; name[i] != 0; i++) { + if (j >= 11) { + return; + } + if (name[i] == '.' && j <= 8) { + j = 8; + } else { + s[j] = name[i]; + if ('a' <= s[j] && s[j] <= 'z') { + s[j] -= 0x20; + } + j++; + } + } + for (i = 0;; i++) { + if (finfo[i].name[0] == 0x00 || finfo[i].name[0] == 0xe5) { + finfo = finfo + i; + break; + } + if (i >= max && finfo != get_dm(vfs).root_directory) { + for (int j = 1; FindForCount(j, get_dm(vfs).directory_list) != NULL; + j++) { + struct List *l = FindForCount(j, get_dm(vfs).directory_list); + if ((struct FAT_FILEINFO *)l->val == finfo) { + max += get_dm(vfs).ClustnoBytes / 32; + FindForCount(j, get_dm(vfs).directory_max_list)->val = max; + struct FAT_FILEINFO *finfo_ = + (struct FAT_FILEINFO *)realloc((void *)finfo, max * 32); + if (get_now_dir(vfs) == finfo) { + get_now_dir(vfs) = finfo_; + } + finfo = finfo_; + l->val = finfo; + break; + } + } + int end = clustno_end(get_dm(vfs).type), last; + for (int j = get_clustno(finfo->clustno_high, finfo->clustno_low);; + j = get_dm(vfs).fat[j]) { + if (get_dm(vfs).fat[j] == end) { + last = j; + break; + } + } + for (int j = 0; j != get_dm(vfs).FatMaxTerms; j++) { + if (!get_dm(vfs).fat[j]) { + get_dm(vfs).fat[last] = j; + get_dm(vfs).fat[j] = end; + get_dm(vfs).FatClustnoFlags[j] = true; + break; + } + } + i--; + } + } + for (i = 0; i != 8; i++) { + finfo->name[i] = s[i]; + } + for (i = 8; i != 11; i++) { + finfo->ext[i - 8] = s[i]; + } + finfo->type = 0x20; + for (int i = 0; i != get_dm(vfs).FatMaxTerms; i++) { + if (!get_dm(vfs).fat[i]) { + finfo->clustno_low = i & 0xffff; + finfo->clustno_high = i >> 16; + int end = clustno_end(get_dm(vfs).type); + get_dm(vfs).fat[i] = end; + get_dm(vfs).FatClustnoFlags[i] = true; + break; + } + } + finfo->reserve = 0; + finfo->update_time = get_fat_time(get_hour(), get_min()); + finfo->update_date = + get_fat_date(get_year(), get_mon(), get_day_of_month()); + finfo->size = 0; + file_saveinfo(Get_dictaddr(path, vfs), vfs); + file_savefat(get_dm(vfs).fat, + get_clustno(finfo->clustno_high, finfo->clustno_low), 1, vfs); + return 1; +} +int changedict(char *dictname, vfs_t *vfs) { + // cd命令的依赖函数 + strtoupper(dictname); + printf("%s\n",dictname); + if (strcmp(dictname, "/") == 0) { + while (vfs->path->ctl->all != 0) { + kfree((FindForCount(vfs->path->ctl->all, vfs->path)->val)); + DeleteVal(vfs->path->ctl->all, vfs->path); + } + get_now_dir(vfs) = get_dm(vfs).root_directory; + return 1; + } + struct FAT_FILEINFO *finfo = dict_search( + dictname, get_now_dir(vfs), get_directory_max(get_now_dir(vfs), vfs)); + // 找文件夹 + if (finfo == 0) { + // 没找到 + return 0; + } + if (get_clustno(finfo->clustno_high, finfo->clustno_low) == 0) { + // 根目录 + while (vfs->path->ctl->all != 0) { + kfree((FindForCount(vfs->path->ctl->all, vfs->path)->val)); + DeleteVal(vfs->path->ctl->all, vfs->path); + } + get_now_dir(vfs) = get_dm(vfs).root_directory; + return 1; + } + //..进行特殊的处理 + //.不进行处理 + // 其他按照下面的方式处理 + if (strcmp(dictname, "..") != 0 && strcmp(dictname, ".") != 0) { + char *dict = kmalloc(255); + strcpy(dict, dictname); + AddVal(dict, vfs->path); + } + + if (strcmp(dictname, "..") == 0) { + kfree((FindForCount(vfs->path->ctl->all, vfs->path)->val)); + DeleteVal(vfs->path->ctl->all, vfs->path); + } + for (int count = 1; + FindForCount(count, get_dm(vfs).directory_clustno_list) != NULL; + count++) { + struct List *list = FindForCount(count, get_dm(vfs).directory_clustno_list); + if (get_clustno(finfo->clustno_high, finfo->clustno_low) == list->val) { + list = FindForCount(count, get_dm(vfs).directory_list); + get_now_dir(vfs) = (struct FAT_FILEINFO *)list->val; + break; + } + } + return 1; +} +int rename(char *src_name, char *dst_name, vfs_t *vfs) { + strtoupper(src_name); + strtoupper(dst_name); + char name[9], ext[4]; + int i; + memclean(name, 9); + memclean(ext, 4); + for (i = 0; dst_name[i] != '.'; i++) { + name[i] = dst_name[i]; + } + i++; + for (int j = 0; i != strlen(dst_name); i++, j++) { + ext[j] = dst_name[i]; + } + struct FAT_FILEINFO *finfo = Get_File_Address(src_name, vfs); + if (finfo == 0 || finfo->type == 0x01 || finfo->type == 0x04) { + return 0; + } + memset((void *)finfo->name, ' ', 11); + for (i = 0; i != strlen(name); i++) { + finfo->name[i] = name[i]; + } + for (i = 0; i != strlen(ext); i++) { + finfo->ext[i] = ext[i]; + } + file_saveinfo(Get_dictaddr(src_name, vfs), vfs); + return 1; +} +int format(char drive) { + +} +int attrib(char *filename, ftype type, struct vfs_t *vfs) { + struct FAT_FILEINFO *finfo = Get_File_Address(filename, vfs); + if (finfo == 0) { + return 0; + } + if (type == FLE) + finfo->type = 0x20; + else if (type == RDO) + finfo->type = 0x01; + else if (type == HID) + finfo->type = 0x02; + else if (type == SYS) + finfo->type = 0x04; + else + return 0; + file_saveinfo(Get_dictaddr(filename, vfs), vfs); + return 1; +} +void fat_InitFS(struct vfs_t *vfs, uint8_t disk_number) { + vfs->cache = kmalloc(sizeof(fat_cache)); + void *boot_sector = kmalloc(512); + Disk_Read(0, 1, boot_sector, disk_number); + + if (memcmp(boot_sector + BS_FileSysType, "FAT12 ", 8) == 0) { + get_dm(vfs).type = 12; + } else if (memcmp(boot_sector + BS_FileSysType, "FAT16 ", 8) == 0) { + get_dm(vfs).type = 16; + } else if (memcmp(boot_sector + BS_FileSysType + BPB_Fat32ExtByts, "FAT32 ", + 8) == 0) { + get_dm(vfs).type = 32; + } + get_dm(vfs).SectorBytes = *(unsigned short *)(boot_sector + BPB_BytsPerSec); + get_dm(vfs).RootMaxFiles = *(unsigned short *)(boot_sector + BPB_RootEntCnt); + get_dm(vfs).ClustnoBytes = get_dm(vfs).SectorBytes * + *(unsigned char *)(boot_sector + BPB_SecPerClus); + get_dm(vfs).Fat1Address = *(unsigned short *)(boot_sector + BPB_RsvdSecCnt) * + get_dm(vfs).SectorBytes; + if (get_dm(vfs).type != 32) { + get_dm(vfs).RootDictAddress = + (*(unsigned char *)(boot_sector + BPB_NumFATs) * + *(unsigned short *)(boot_sector + BPB_FATSz16) + + *(unsigned short *)(boot_sector + BPB_RsvdSecCnt)) * + get_dm(vfs).SectorBytes; + get_dm(vfs).FileDataAddress = + get_dm(vfs).RootDictAddress + get_dm(vfs).RootMaxFiles * 32; + if (*(unsigned short *)(boot_sector + BPB_TotSec16) != 0) { + get_dm(vfs).imgTotalSize = + *(unsigned short *)(boot_sector + BPB_TotSec16) * + get_dm(vfs).SectorBytes; + } else { + get_dm(vfs).imgTotalSize = *(unsigned int *)(boot_sector + BPB_TotSec32) * + get_dm(vfs).SectorBytes; + } + get_dm(vfs).Fat2Address = get_dm(vfs).Fat1Address + + *(unsigned short *)(boot_sector + BPB_FATSz16) * + get_dm(vfs).SectorBytes; + } else { + get_dm(vfs).FileDataAddress = + (*(unsigned char *)(boot_sector + BPB_NumFATs) * + *(unsigned int *)(boot_sector + BPB_FATSz32) + + *(unsigned short *)(boot_sector + BPB_RsvdSecCnt)) * + get_dm(vfs).SectorBytes; + get_dm(vfs).RootDictAddress = + get_dm(vfs).FileDataAddress + + (*(unsigned int *)(boot_sector + BPB_RootClus) - 2) * + get_dm(vfs).ClustnoBytes; + get_dm(vfs).imgTotalSize = + *(unsigned int *)(boot_sector + BPB_TotSec32) * get_dm(vfs).SectorBytes; + get_dm(vfs).Fat2Address = + get_dm(vfs).Fat1Address + + *(unsigned int *)(boot_sector + BPB_FATSz32) * get_dm(vfs).SectorBytes; + get_dm(vfs).RootMaxFiles = get_dm(vfs).ClustnoBytes / 32; + } + get_dm(vfs).FatMaxTerms = + (get_dm(vfs).Fat2Address - get_dm(vfs).Fat1Address) * 8 / + get_dm(vfs).type; + + uint32_t sec = (get_dm(vfs).RootDictAddress + get_dm(vfs).RootMaxFiles * 32) / + get_dm(vfs).SectorBytes; + get_dm(vfs).ADR_DISKIMG = (unsigned int)kmalloc(get_dm(vfs).RootDictAddress + + get_dm(vfs).RootMaxFiles * 32); + printf("DISK NUMBER :%x %d\n",disk_number,sec); + Disk_Read(0, sec, (void *)get_dm(vfs).ADR_DISKIMG, disk_number); + + + get_dm(vfs).fat = kmalloc(get_dm(vfs).FatMaxTerms * sizeof(int)); + get_dm(vfs).FatClustnoFlags = kmalloc(get_dm(vfs).FatMaxTerms * sizeof(char)); + read_fat((unsigned char *)(get_dm(vfs).ADR_DISKIMG + + (unsigned int)get_dm(vfs).Fat1Address), + get_dm(vfs).fat, get_dm(vfs).FatClustnoFlags, + get_dm(vfs).FatMaxTerms, get_dm(vfs).type); + get_dm(vfs).root_directory = + (struct FAT_FILEINFO *)kmalloc(get_dm(vfs).RootMaxFiles * 32); + memcpy((void *)get_dm(vfs).root_directory, + (void *)get_dm(vfs).ADR_DISKIMG + get_dm(vfs).RootDictAddress, + get_dm(vfs).RootMaxFiles * 32); + get_dm(vfs).directory_list = (struct List *)NewList(); + get_dm(vfs).directory_clustno_list = (struct List *)NewList(); + get_dm(vfs).directory_max_list = (struct List *)NewList(); + struct FAT_FILEINFO *finfo = get_dm(vfs).root_directory; + + for (int i = 0; i != get_dm(vfs).RootMaxFiles; i++) { + if (finfo[i].type == 0x10 && finfo[i].name[0] != 0xe5) { + AddVal(get_clustno(finfo[i].clustno_high, finfo[i].clustno_low), + (struct List *)get_dm(vfs).directory_clustno_list); + int end = clustno_end(get_dm(vfs).type), k = 1; + for (int j = get_clustno(finfo[i].clustno_high, finfo[i].clustno_low); + get_dm(vfs).fat[j] != end; j = get_dm(vfs).fat[j], k++) + ; + void *directory_alloc = kmalloc(k * get_dm(vfs).ClustnoBytes); + for (int j = get_clustno(finfo[i].clustno_high, finfo[i].clustno_low), + l = 0; + l != k; l++) { + uint32_t sec1 = + (get_dm(vfs).FileDataAddress + (j - 2) * get_dm(vfs).ClustnoBytes) / + get_dm(vfs).SectorBytes; + Disk_Read(sec1, get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes, + (char *)directory_alloc + l * get_dm(vfs).SectorBytes, + disk_number); + j = get_dm(vfs).fat[j]; + } + AddVal((int)directory_alloc, (struct List *)get_dm(vfs).directory_list); + AddVal(k * get_dm(vfs).ClustnoBytes / 32, + (struct List *)get_dm(vfs).directory_max_list); + } + if (finfo[i].name[0] == 0) { + break; + } + } + + for (int i = 1; + FindForCount(i, (struct List *)get_dm(vfs).directory_list) != NULL; + i++) { + struct List *list = + FindForCount(i, (struct List *)get_dm(vfs).directory_list); + finfo = (struct FAT_FILEINFO *)list->val; + for (int j = 0; j != get_directory_max(finfo, vfs); j++) { + if (finfo[j].type == 0x10 && finfo[j].name[0] != 0xe5 && + strncmp(".", (char *)finfo[j].name, 1) != 0 && + strncmp("..", (char *)finfo[j].name, 2) != 0) { + AddVal(get_clustno(finfo[j].clustno_high, finfo[j].clustno_low), + (struct List *)get_dm(vfs).directory_clustno_list); + int end = clustno_end(get_dm(vfs).type), k = 1; + for (int m = get_clustno(finfo[j].clustno_high, finfo[j].clustno_low); + get_dm(vfs).fat[m] != end; m = get_dm(vfs).fat[m], k++) + ; + void *directory_alloc = kmalloc(k * get_dm(vfs).ClustnoBytes); + for (int m = get_clustno(finfo[j].clustno_high, finfo[j].clustno_low), + l = 0; + l != k; l++) { + uint32_t sec1 = (get_dm(vfs).FileDataAddress + + (m - 2) * get_dm(vfs).ClustnoBytes) / + get_dm(vfs).SectorBytes; + Disk_Read(sec1, get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes, + (char *)directory_alloc + l * get_dm(vfs).SectorBytes, + disk_number); + m = get_dm(vfs).fat[m]; + } + AddVal((int)directory_alloc, (struct List *)get_dm(vfs).directory_list); + AddVal(k * get_dm(vfs).ClustnoBytes / 32, + (struct List *)get_dm(vfs).directory_max_list); + } + if (finfo[j].name[0] == 0) { + break; + } + } + } + kfree((boot_sector)); +} +void Fat_CopyCache(struct vfs_t *dest, struct vfs_t *src) { + dest->cache = kmalloc(sizeof(fat_cache)); + memcpy(dest->cache, src->cache, sizeof(fat_cache)); +} +bool Fat_cd(struct vfs_t *vfs, char *dictName) { + return changedict(dictName, vfs); +} +bool Fat_ReadFile(struct vfs_t *vfs, char *path, char *buffer) { + struct FAT_FILEINFO *finfo; + finfo = Get_File_Address(path, vfs); + if (finfo == 0) { + return 0; + } else { + file_loadfile(get_clustno(finfo->clustno_high, finfo->clustno_low), + finfo->size, buffer, get_dm(vfs).fat, vfs); + return 1; + } +} +bool Fat_WriteFile(struct vfs_t *vfs, char *path, char *buffer, int size) { + struct FAT_FILEINFO *finfo = Get_File_Address(path, vfs); + file_savefile(get_clustno(finfo->clustno_high, finfo->clustno_low), size, + buffer, get_dm(vfs).fat, get_dm(vfs).FatClustnoFlags, vfs); + finfo->size = size; + file_saveinfo(Get_dictaddr(path, vfs), vfs); +} +List *Fat_ListFile(struct vfs_t *vfs, char *dictpath) { + struct FAT_FILEINFO *finfo = Get_dictaddr(dictpath, vfs); + if(finfo == NULL) { + return NULL; + } + List *result = NewList(); + char s[30]; + for (int i = 0; i != 30; i++) { + s[i] = 0; + } + for (int i = 0; i < get_directory_max(finfo, vfs); i++) { + if (finfo[i].name[0] == 0x00) { + break; + } + if (finfo[i].name[0] != 0xe5) { + if ((finfo[i].type & 0x18) == 0 || finfo[i].type == 0x10) { + for (int j = 0; j < 8; j++) { + s[j] = finfo[i].name[j]; + } + s[8] = '.'; + if (finfo[i].ext[0] == ' ') { + s[8] = 0; + } else { + s[9] = finfo[i].ext[0]; + s[10] = finfo[i].ext[1]; + s[11] = finfo[i].ext[2]; + } + if (s[0] != '+') { + vfs_file *d = kmalloc(sizeof(vfs_file)); + if (finfo[i].type == 0x10) { + d->type = DIR; + } else if (finfo[i].type == 0x20) { + d->type = FLE; + } else if (finfo[i].type == 0x01) { + d->type = RDO; + } else if (finfo[i].type == 0x02) { + d->type = HID; + } else if (finfo[i].type == 0x04) { + d->type = SYS; + } + d->year = (finfo[i].update_date & 65024) >> 9; + d->year += 1980; + d->month = (finfo[i].update_date & 480) >> 5; + d->day = finfo[i].update_date & 31; + d->hour = (finfo[i].update_time & 63488) >> 11; + d->minute = (finfo[i].update_time & 2016) >> 5; + d->size = finfo[i].size; + int q = 0; + for (int k = 0; k < 12 && s[k] != 0; ++k) { + if (s[k] != ' ') { + d->name[q++] = s[k]; + } + } + d->name[q] = 0; + // printk("d->name = %s\n", d->name); + AddVal(d, result); + } + } + } + } + return result; +} +bool Fat_RenameFile(struct vfs_t *vfs, char *filename, char *filename_of_new) { + return rename(filename, filename_of_new, vfs); +} +bool Fat_CreateFile(struct vfs_t *vfs, char *filename) { + return mkfile(filename, vfs); +} +void Fat_DeleteFs(struct vfs_t *vfs) { + kfree((void *)get_dm(vfs).ADR_DISKIMG); + kfree(get_dm(vfs).fat); + kfree(get_dm(vfs).FatClustnoFlags); + kfree(get_dm(vfs).root_directory); + DeleteList(get_dm(vfs).directory_clustno_list); + DeleteList(get_dm(vfs).directory_list); +} +bool Fat_Check(uint8_t disk_number) { + uint8_t *boot_sec = kmalloc(512); + Disk_Read(0, 1, boot_sec, disk_number); + // logk("disk number = %02x\n", disk_number); + for(int i = 0;i<0x200;i++) printf("%02x ",boot_sec[i]); + if (memcmp(boot_sec + BS_FileSysType, "FAT12 ", 8) == 0 || + memcmp(boot_sec + BS_FileSysType, "FAT16 ", 8) == 0 || + memcmp(boot_sec + BS_FileSysType + BPB_Fat32ExtByts, "FAT32 ", 8) == + 0) { + kfree((boot_sec)); + return true; + } + kfree((boot_sec)); + return false; +} +bool Fat_DelFile(struct vfs_t *vfs, char *path) { return del(path, vfs); } +bool Fat_DelDict(struct vfs_t *vfs, char *path) { return deldir(path, vfs); } +int Fat_FileSize(struct vfs_t *vfs, char *filename) { + if (Get_File_Address(filename, vfs) == NULL) { + return -1; + } + return Get_File_Address(filename, vfs)->size; +} +bool Fat_Format(uint8_t disk_number) { return format(disk_number); } +bool Fat_CreateDict(struct vfs_t *vfs, char *filename) { + struct FAT_FILEINFO *finfo = Get_dictaddr(filename, vfs); + int last_clustno = finfo[0].clustno_low; + if (finfo == get_dm(vfs).root_directory) { + last_clustno = 0; + } + + return mkdir(filename, last_clustno, vfs); +} +bool Fat_Attrib(struct vfs_t *vfs, char *filename, ftype type) { + return attrib(filename, type, vfs); +} +vfs_file *Fat_FileInfo(struct vfs_t *vfs, char *filename) { + struct FAT_FILEINFO *finfo = Get_File_Address(filename, vfs); + if (finfo == NULL) { + return NULL; + } + vfs_file *result = (vfs_file *)kmalloc(sizeof(vfs_file)); + char s[30]; + for (int i = 0; i != 30; i++) { + s[i] = 0; + } + for (int i = 0; i < 8; i++) { + s[i] = finfo->name[i]; + } + s[8] = '.'; + if (finfo->ext[0] == ' ') { + s[8] = 0; + } else { + s[9] = finfo->ext[0]; + s[10] = finfo->ext[1]; + s[11] = finfo->ext[2]; + } + int i = 0; + for (int j = 0; i < 12 && s[i] != 0; i++) { + if (s[i] != ' ') { + result->name[j++] = s[i]; + } + } + s[i] = '\0'; + if (finfo->type == 0x10) { + result->type = DIR; + } else if (finfo->type == 0x20) { + result->type = FLE; + } else if (finfo->type == 0x01) { + result->type = RDO; + } else if (finfo->type == 0x02) { + result->type = HID; + } else if (finfo->type == 0x04) { + result->type = SYS; + } + result->year = (finfo->update_date & 65024) >> 9; + result->year += 1980; + result->month = (finfo->update_date & 480) >> 5; + result->day = finfo->update_date & 31; + result->hour = (finfo->update_time & 63488) >> 11; + result->minute = (finfo->update_time & 2016) >> 5; + result->size = finfo->size; + return result; +} +void Register_fat_fileSys() { + vfs_t fs; + fs.flag = 1; + fs.cache = NULL; + strcpy(fs.FSName, "FAT"); + fs.CopyCache = Fat_CopyCache; + fs.Format = Fat_Format; + fs.CreateFile = Fat_CreateFile; + fs.CreateDict = Fat_CreateDict; + fs.DelDict = Fat_DelDict; + fs.DelFile = Fat_DelFile; + fs.ReadFile = Fat_ReadFile; + fs.WriteFile = Fat_WriteFile; + fs.DeleteFs = Fat_DeleteFs; + fs.cd = Fat_cd; + fs.FileSize = Fat_FileSize; + fs.Check = Fat_Check; + fs.ListFile = Fat_ListFile; + fs.InitFs = fat_InitFS; + fs.RenameFile = Fat_RenameFile; + fs.Attrib = Fat_Attrib; + fs.FileInfo = Fat_FileInfo; + vfs_register_fs(fs); +} diff --git a/fs/iso9660.c b/fs/iso9660.c new file mode 100644 index 0000000..d45b879 --- /dev/null +++ b/fs/iso9660.c @@ -0,0 +1,328 @@ +#include "../include/iso9660.h" +#include "../include/memory.h" +#include "../include/vfs.h" +#include "../include/vdisk.h" + +#define l9660_seekdir(dir, pos) (l9660_seek(&(dir)->file, L9660_SEEK_SET, (pos))) +#define l9660_telldir(dir) (l9660_tell(&(dir)->file)) + +#define SEEK_END L9660_SEEK_END +#define SEEK_SET L9660_SEEK_SET +#define SEEK_CUR L9660_SEEK_CUR + +#define DENT_EXISTS (1 << 0) +#define DENT_ISDIR (1 << 1) +#define DENT_ASSOCIATED (1 << 2) +#define DENT_RECORD (1 << 3) +#define DENT_PROTECTION (1 << 4) +#define DENT_MULTIEXTENT (1 << 5) + +#define PVD(vdesc) ((l9660_vdesc_primary*)(vdesc)) + +#ifdef L9660_BIG_ENDIAN +#define READ16(v) (((v).be[1]) | ((v).be[0] << 8)) +#define READ32(v) (((v).be[3]) | ((v).be[2] << 8) | ((v).be[1]) << 16 | ((v).be[0] << 24)) +#else +#define READ16(v) (((v).le[0]) | ((v).le[1] << 8)) +#define READ32(v) (((v).le[0]) | ((v).le[1] << 8) | ((v).le[2]) << 16 | ((v).le[3] << 24)) +#endif + +#ifndef L9660_SINGLEBUFFER +#define HAVEBUFFER(f) (true) +#define BUF(f) ((f)->buf) +#else +#define HAVEBUFFER(f) ((f) == last_file) +#define BUF(f) (gbuf) +static l9660_file *last_file; +static char gbuf[2048]; +#endif + +l9660_fs *fs; + +static char *strchrnul(const char *s, int c) { + while (*s) { + if ((*s++) == c) + break; + } + return (char *) s; +} + +static inline uint16_t +fsectoff(l9660_file +*f) +{ +return f->position % 2048; +} + +static inline uint32_t +fsector(l9660_file +*f) +{ +return f->position / 2048; +} + +static inline uint32_t +fnextsectpos(l9660_file +*f) +{ +return (f->position + 2047) & ~2047; +} + +l9660_status l9660_openfs(l9660_fs *fs, bool (*read_sector)(l9660_fs *fs, void *buf, uint32_t sector,uint8_t disk_number),uint8_t disk_number){ +fs-> +read_sector = read_sector; + +#ifndef L9660_SINGLEBUFFER +l9660_vdesc_primary *pvd = PVD(&fs->pvd); +#else +last_file = NULL; + l9660_vdesc_primary *pvd = PVD(gbuf); +#endif +uint32_t idx = 0x10; +for (;;) { +// Read next sector +if (! +read_sector(fs, pvd, idx, disk_number +)) +return +L9660_EIO; + +// Validate magic +if ( +memcmp(pvd +->hdr.magic, "CD001", 5) != 0) +return +L9660_EBADFS; + +if (pvd->hdr.type == 1) +break; // Found PVD +else if(pvd->hdr.type == 255) +return +L9660_EBADFS; +} + +#ifdef L9660_SINGLEBUFFER +memcpy(&fs->root_dir_ent, &pvd->root_dir_ent, pvd->root_dir_ent.length); +#endif + +return +L9660_OK; +} + +l9660_status l9660_fs_open_root(l9660_dir *dir, l9660_fs *fs) { + l9660_file * f = &dir->file; +#ifndef L9660_SINGLEBUFFER + l9660_dirent *dirent = &PVD(&fs->pvd)->root_dir_ent; +#else + l9660_dirent *dirent = &fs->root_dir_ent; +#endif + + f->fs = fs; + f->first_sector = READ32(dirent->sector); + f->length = READ32(dirent->size); + f->position = 0; + + return L9660_OK; +} + +static l9660_status buffer(l9660_file *f) { +#ifdef L9660_SINGLEBUFFER + last_file = f; +#endif + if (!f->fs->read_sector(f->fs, BUF(f), f->first_sector + f->position / 2048)) + return L9660_EIO; + else + return L9660_OK; +} + +static l9660_status prebuffer(l9660_file *f) { + if (!HAVEBUFFER(f) || (f->position % 2048) == 0) + return buffer(f); + else return L9660_OK; +} + +static l9660_status openat_raw(l9660_file *child, l9660_dir *parent, const char *name, bool isdir) { + l9660_status rv; + l9660_dirent *dent = NULL; + if ((rv = l9660_seekdir(parent, 0))) return rv; + + do { + const char *seg = name; + name = strchrnul(name, '/'); + size_t seglen = name - seg; + + /* ISO9660 stores '.' as '\0' */ + if (seglen == 1 && *seg == '.') + seg = "\0"; + + /* ISO9660 stores ".." as '\1' */ + if (seglen == 2 && seg[0] == '.' && seg[1] == '.') { + seg = "\1"; + seglen = 1; + } + + for (;;) { + if ((rv = l9660_readdir(parent, &dent))) + return rv; + + /* EOD */ + if (!dent) + return L9660_ENOENT; + +#ifdef DEBUG + print_dirent(dent); +#endif + + /* wrong length */ + if (seglen > dent->name_len) + continue; + + /* check name */ + if (memcmp(seg, dent->name, seglen) != 0) + continue; + + /* check for a revision tag */ + if (dent->name_len > seglen && dent->name[seglen] != ';') + continue; + + /* all tests pass */ + break; + } + + child->fs = parent->file.fs; + child->first_sector = READ32(dent->sector) + dent->xattr_length; + child->length = READ32(dent->size); + child->position = 0; + + if (*name && (dent->flags & DENT_ISDIR) != 0) + return L9660_ENOTDIR; + + parent = (l9660_dir *) child; + } while (*name); + + if (isdir) { + if ((dent->flags & DENT_ISDIR) == 0) + return L9660_ENOTDIR; + } else { + if ((dent->flags & DENT_ISDIR) != 0) + return L9660_ENOTFILE; + } + + return L9660_OK; +} + +l9660_status l9660_opendirat(l9660_dir *dir, l9660_dir *parent, const char *path) { + return openat_raw(&dir->file, parent, path, true); +} + +static inline unsigned aligneven(unsigned v) { + return v + (v & 1); +} + +l9660_status l9660_readdir(l9660_dir *dir, l9660_dirent **pdirent) { + l9660_status rv; + l9660_file * f = &dir->file; + + rebuffer: + if (f->position >= f->length) { + *pdirent = NULL; + return L9660_OK; + } + + if ((rv = prebuffer(f))) + return rv; + + char *off = BUF(f) + fsectoff(f); + if (*off == 0) { + // Padded end of sector + f->position = fnextsectpos(f); + goto rebuffer; + } + + l9660_dirent *dirent = (l9660_dirent *) off; + f->position += aligneven(dirent->length); + + *pdirent = dirent; + return L9660_OK; +} + +l9660_status l9660_openat(l9660_file *child, l9660_dir *parent, const char *name) { + return openat_raw(child, parent, name, false); +} + +/*! Seek the file to \p offset from \p whence */ +l9660_status l9660_seek(l9660_file *f, int whence, int32_t offset) { + l9660_status rv; + uint32_t cursect = fsector(f); + + switch (whence) { + case SEEK_SET: + f->position = offset; + break; + + case SEEK_CUR: + f->position = f->position + offset; + break; + + case SEEK_END: + f->position = f->length - offset; + break; + } + + if (fsector(f) != cursect && fsectoff(f) != 0) { + if ((rv = buffer(f))) + return rv; + } + + return L9660_OK; +} + +uint32_t l9660_tell(l9660_file *f) { + return f->position; +} + +l9660_status l9660_read(l9660_file *f, void *buf, size_t size, size_t *read) { + l9660_status rv; + + if ((rv = prebuffer(f))) + return rv; + + uint16_t rem = 2048 - fsectoff(f); + if (rem > f->length - f->position) + rem = f->length - f->position; + if (rem < size) + size = rem; + + memcpy(buf, BUF(f) + fsectoff(f), size); + + *read = size; + f->position += size; + + return L9660_OK; +} + +bool read_sector(l9660_fs *fs, void *buf, uint32_t sector,uint8_t disk_number){ + return false; +} + +bool ISO_Check(uint8_t disk_number){ + l9660_openfs(fs,read_sector,disk_number); + return false; +} + +void ISO_InitFs(struct vfs_t *vfs, uint8_t disk_number){ + +} + +void init_iso9660(){ + vfs_t fs; + fs.flag = 1; + fs.cache = NULL; + strcpy(fs.FSName, "ISO9660"); + + fs.Check = ISO_Check; + fs.InitFs = ISO_InitFs; + + + //vfs_register_fs(fs); +} diff --git a/fs/vfs.c b/fs/vfs.c index e360ef8..a492b2f 100644 --- a/fs/vfs.c +++ b/fs/vfs.c @@ -83,9 +83,10 @@ bool vfs_mount_disk(uint8_t disk_number, uint8_t drive) { printf("can not find a seat of vfsMount_Stl(it's full)\n"); return false; } + vfs_t *fs = check_disk_fs(disk_number); if (!fs) { - printf("unknow file system.\n"); + printf("[FileSystem]: Unknown file system.\n"); return false; } *seat = *fs; @@ -178,6 +179,41 @@ bool vfs_delfile(char *filename) { return result; } +bool vfs_change_path(char *dictName) { + char *buf = kmalloc(strlen(dictName) + 1); + char *r = buf; + memcpy(buf, dictName, strlen(dictName) + 1); + int i = 0; + if (buf[i] == '/' || buf[i] == '\\') { + if (!vfs_now->cd(vfs_now, "/")) { + kfree(r); + return false; + } + i++; + buf++; + } + + for (;; i++) { + if (buf[i] == '/' || buf[i] == '\\') { + buf[i] = 0; + if (!vfs_now->cd(vfs_now, buf)) { + kfree(r); + return false; + } + buf += strlen(buf) + 1; + } + if (buf[i] == 0) { + if (!vfs_now->cd(vfs_now, buf)) { + kfree(r); + return false; + } + break; + } + } + kfree(r); + return true; +} + bool vfs_deldir(char *dictname) { char *new_path = kmalloc(strlen(dictname) + 1); strcpy(new_path, dictname); @@ -206,6 +242,7 @@ bool vfs_createfile(char *filename) { bool vfs_createdict(char *filename) { char *new_path = kmalloc(strlen(filename) + 1); + memclean(new_path, strlen(filename) + 1); strcpy(new_path, filename); vfs_t *vfs = ParsePath(new_path); if (vfs == NULL) { @@ -254,17 +291,41 @@ bool vfs_format(uint8_t disk_number, char *FSName) { vfs_file *vfs_fileinfo(char *filename) { char *new_path = kmalloc(strlen(filename) + 1); + memclean(new_path,strlen(filename) + 1); strcpy(new_path, filename); vfs_t *vfs = ParsePath(new_path); if (vfs == NULL) { kfree(new_path); return false; } + + + vfs_file *result = vfs->FileInfo(vfs, new_path); kfree(new_path); return result; } +vfs_file *get_cur_file(char* filename){ + vfs_file *file = NULL; + List *ls = vfs_listfile(""); + strtoupper(filename); + for (int i = 1; FindForCount(i, ls) != NULL; i++) { + vfs_file *d = (vfs_file *) FindForCount(i, ls)->val; + if(strcmp(d->name, filename) == 0){ + file = d; + break; + } + kfree(d); + } + DeleteList(ls); + kfree(ls); + + + + return file; +} + bool vfs_change_disk(uint8_t drive) { if (vfs_now != NULL) { while (FindForCount(1, vfs_now->path) != NULL) { @@ -275,10 +336,12 @@ bool vfs_change_disk(uint8_t drive) { DeleteList(vfs_now->path); kfree(vfs_now); } + vfs_t *f; if (!(f = drive2fs(drive))) { return false; // 没有mount } + vfs_now = kmalloc(sizeof(vfs_t)); memcpy(vfs_now, f, sizeof(vfs_t)); f->CopyCache(vfs_now, f); @@ -287,6 +350,44 @@ bool vfs_change_disk(uint8_t drive) { return true; } +void vfs_getPath(char *buffer) { + char *path; + List *l; + buffer[0] = 0; + insert_char(buffer, 0, vfs_now->drive); + insert_char(buffer, 1, ':'); + insert_char(buffer, 2, '\\'); + int pos = strlen(buffer); + for (int i = 1; FindForCount(i, vfs_now->path) != NULL; i++) { + l = FindForCount(i, vfs_now->path); + path = (char *)l->val; + insert_str(buffer, path, pos); + pos += strlen(path); + insert_char(buffer, pos, '\\'); + pos++; + } + delete_char(buffer, pos - 1); +} + +void vfs_getPath_no_drive(char *buffer) { + char *path; + List *l; + buffer[0] = 0; + int pos = strlen(buffer); + int i; + for (i = 1; FindForCount(i, vfs_now->path) != NULL; i++) { + l = FindForCount(i, vfs_now->path); + path = (char *)l->val; + insert_char(buffer, pos, '/'); + pos++; + insert_str(buffer, path, pos); + pos += strlen(path); + } + if (i == 1) { + insert_char(buffer, 0, '/'); + } +} + void init_vfs() { for (int i = 0; i < 26; i++) { vfsstl[i].flag = 0; diff --git a/include/arp.h b/include/arp.h index d8d24f4..25dab61 100644 --- a/include/arp.h +++ b/include/arp.h @@ -22,5 +22,5 @@ struct ARPMessage { uint64_t IPParseMAC(uint32_t dstIP); uint8_t *ARP_Packet(uint64_t dest_mac, uint32_t dest_ip, uint64_t src_mac, uint32_t src_ip, uint16_t command); - +void arp_handler(void *base); #endif diff --git a/include/common.h b/include/common.h index 53f033b..bdfa3d1 100644 --- a/include/common.h +++ b/include/common.h @@ -46,7 +46,7 @@ char *int64_to_str_dec(int64_t num, int flag, int width); char *uint32_to_str_hex(uint32_t num, int flag, int width); char *uint64_to_str_hex(uint64_t num, int flag, int width); char *uint32_to_str_oct(uint32_t num, int flag, int width); -char *insert_str(char *buf, const char *str); +void insert_str(char *str, char *insert_str, int pos); int vsprintf(char *buf, const char *fmt, va_list args); int sprintf(char *buf, const char *fmt, ...); long int strtol(const char *str,char **endptr,int base); diff --git a/include/fat.h b/include/fat.h new file mode 100644 index 0000000..49c3b81 --- /dev/null +++ b/include/fat.h @@ -0,0 +1,110 @@ +#ifndef CRASHPOWERDOS_FAT_H +#define CRASHPOWERDOS_FAT_H + +#define BS_FileSysType 54 +#define BPB_Fat32ExtByts 28 +#define BS_jmpBoot 0 +#define BS_OEMName 3 +#define BPB_BytsPerSec 11 +#define BPB_SecPerClus 13 +#define BPB_RsvdSecCnt 14 +#define BPB_NumFATs 16 +#define BPB_RootEntCnt 17 +#define BPB_TotSec16 19 +#define BPB_Media 21 +#define BPB_FATSz16 22 +#define BPB_SecPerTrk 24 +#define BPB_NumHeads 26 +#define BPB_HiddSec 28 +#define BPB_TotSec32 32 +#define BPB_FATSz32 36 +#define BPB_ExtFlags 40 +#define BPB_FSVer 42 +#define BPB_RootClus 44 +#define BPB_FSInfo 48 +#define BPB_BkBootSec 50 +#define BPB_Reserved 52 +#define BPB_Fat32ExtByts 28 +#define BS_DrvNum 36 +#define BS_Reserved1 37 +#define BS_BootSig 38 +#define BS_VolD 39 +#define BS_VolLab 43 +#define BS_FileSysType 54 +#define EOF -1 +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +#include "list.h" +#include "vfs.h" + +struct FAT_FILEINFO { + unsigned char name[8], ext[3], type; + char reserve; + unsigned char create_time_tenth; + unsigned short create_time, create_date, access_date, clustno_high; + unsigned short update_time, update_date, clustno_low; + unsigned int size; +}; + +struct FAT_CACHE { + unsigned int ADR_DISKIMG; + struct FAT_FILEINFO *root_directory; + struct List *directory_list; + struct List *directory_clustno_list; + struct List *directory_max_list; + int *fat; + int FatMaxTerms; + unsigned int ClustnoBytes; + unsigned short RootMaxFiles; + unsigned int RootDictAddress; + unsigned int FileDataAddress; + unsigned int imgTotalSize; + unsigned short SectorBytes; + unsigned int Fat1Address, Fat2Address; + unsigned char *FatClustnoFlags; + int type; +}; +typedef struct { + struct FAT_CACHE dm; + struct FAT_FILEINFO *dir; +} fat_cache; + +void read_fat(unsigned char *img, int *fat, unsigned char *ff, int max, + int type); +int get_directory_max(struct FAT_FILEINFO *directory, vfs_t *vfs); +int changedict(char *dictname, vfs_t *vfs); +struct FAT_FILEINFO *dict_search(char *name, struct FAT_FILEINFO *finfo, + int max); +void file_savefat(int *fat, int clustno, int length, vfs_t *vfs); +void file_saveinfo(struct FAT_FILEINFO *directory, vfs_t *vfs); +void file_savefile(int clustno, int size, char *buf, int *fat, + unsigned char *ff, vfs_t *vfs); +void file_loadfile(int clustno, int size, char *buf, int *fat, vfs_t *vfs); +int deldir(char *path, vfs_t *vfs); +int del(char *cmdline, vfs_t *vfs); +int attrib(char *filename, ftype type, struct vfs_t *vfs); +int rename(char *src_name, char *dst_name, vfs_t *vfs); +int mkdir(char *dictname, int last_clust, vfs_t *vfs); +int mkfile(char *name, vfs_t *vfs); +void fat_InitFS(struct vfs_t *vfs, uint8_t disk_number); +bool Fat_Check(uint8_t disk_number); +void Fat_CopyCache(struct vfs_t *dest, struct vfs_t *src); +List *Fat_ListFile(struct vfs_t *vfs, char *dictpath); +bool Fat_WriteFile(struct vfs_t *vfs, char *path, char *buffer, int size); +bool Fat_ReadFile(struct vfs_t *vfs, char *path, char *buffer); +bool Fat_RenameFile(struct vfs_t *vfs, char *filename, char *filename_of_new); +bool Fat_CreateFile(struct vfs_t *vfs, char *filename); +void Fat_DeleteFs(struct vfs_t *vfs); +bool Fat_DelFile(struct vfs_t *vfs, char *path); +bool Fat_DelDict(struct vfs_t *vfs, char *path); +bool Fat_Format(uint8_t disk_number); +vfs_file *Fat_FileInfo(struct vfs_t *vfs, char *filename); +bool Fat_Attrib(struct vfs_t *vfs, char *filename, ftype type); +bool Fat_CreateDict(struct vfs_t *vfs, char *filename); +bool Fat_cd(struct vfs_t *vfs, char *dictName); +struct FAT_FILEINFO *Get_dictaddr(char *path1, vfs_t *vfs); +void Register_fat_fileSys(); + +#endif \ No newline at end of file diff --git a/include/ide.h b/include/ide.h index e14e121..b8ae497 100644 --- a/include/ide.h +++ b/include/ide.h @@ -73,26 +73,26 @@ #define ATA_READ 0x00 #define ATA_WRITE 0x01 +void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2, + unsigned int BAR3, unsigned int BAR4); unsigned char ide_read(unsigned char channel, unsigned char reg); void ide_write(unsigned char channel, unsigned char reg, unsigned char data); void ide_read_buffer(unsigned char channel, unsigned char reg, unsigned int buffer, unsigned int quads); unsigned char ide_polling(unsigned char channel, unsigned int advanced_check); unsigned char ide_print_error(unsigned int drive, unsigned char err); -void ide_wait_irq(); -void ide_irq(); unsigned char ide_ata_access(unsigned char direction, unsigned char drive, unsigned int lba, unsigned char numsects, unsigned short selector, unsigned int edi); -void ide_write_sectors(unsigned char drive, unsigned char numsects, - unsigned int lba, unsigned short es, unsigned int edi); -void ide_read_sectors(unsigned char drive, unsigned char numsects, - unsigned int lba, unsigned short es, unsigned int edi); +void ide_wait_irq(); +void ide_irq(); unsigned char ide_atapi_read(unsigned char drive, unsigned int lba, unsigned char numsects, unsigned short selector, unsigned int edi); +void ide_read_sectors(unsigned char drive, unsigned char numsects, + unsigned int lba, unsigned short es, unsigned int edi); +void ide_write_sectors(unsigned char drive, unsigned char numsects, + unsigned int lba, unsigned short es, unsigned int edi); void ide_atapi_eject(unsigned char drive); -void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2, - unsigned int BAR3, unsigned int BAR4); #endif diff --git a/include/iso9660.h b/include/iso9660.h new file mode 100644 index 0000000..62b8343 --- /dev/null +++ b/include/iso9660.h @@ -0,0 +1,169 @@ +#ifndef CRASHPOWEROS_ISO9660_H +#define CRASHPOWEROS_ISO9660_H + +#define L9660_SEEK_END -1 +#define L9660_SEEK_SET 0 +#define L9660_SEEK_CUR +1 + +#include +#include +#include "common.h" + +typedef enum { + /*! Success! */ + L9660_OK = 0, + /*! read_sector callback returned false */ + L9660_EIO, + /*! file system is bad */ + L9660_EBADFS, + /*! specified name does not exist */ + L9660_ENOENT, + /*! attempted to open a non-file (e.g. a directory) as a file */ + L9660_ENOTFILE, + /*! attempted to open a non-directory (e.g. a file) as a directory + * may be returned by l9660_openat if e.g. you pass path "a/b" and + * "a" is a file + */ + L9660_ENOTDIR, +} l9660_status; + +typedef struct { + uint8_t le[2]; +} l9660_luint16; +typedef struct { + uint8_t be[2]; +} l9660_buint16; +typedef struct { + uint8_t le[2], be[2]; +} l9660_duint16; +typedef struct { + uint8_t le[4]; +} l9660_luint32; +typedef struct { + uint8_t be[4]; +} l9660_buint32; +typedef struct { + uint8_t le[4], be[4]; +} l9660_duint32; + +/* Descriptor time format */ +typedef struct { + char d[17]; +} l9660_desctime; + +/* File time format */ +typedef struct { + char d[7]; +} l9660_filetime; + +/* Directory entry */ +typedef struct { + uint8_t length; + uint8_t xattr_length; + l9660_duint32 sector; + l9660_duint32 size; + l9660_filetime time; + uint8_t flags; + uint8_t unit_size; + uint8_t gap_size; + l9660_duint16 vol_seq_number; + uint8_t name_len; + char name[/*name_len*/]; +} l9660_dirent; + +/* Volume descriptor header */ +typedef struct { + uint8_t type; + char magic[5]; + uint8_t version; +} l9660_vdesc_header; + +/* Primary volume descriptor */ +typedef struct { + l9660_vdesc_header hdr; + char pad0[1]; + char system_id[32]; + char volume_id[32]; + char pad1[8]; + l9660_duint32 volume_space_size; + char pad2[32]; + l9660_duint16 volume_set_size; + l9660_duint16 volume_seq_number; + l9660_duint16 logical_block_size; + l9660_duint32 path_table_size; + l9660_luint32 path_table_le; + l9660_luint32 path_table_opt_le; + l9660_buint32 path_table_be; + l9660_buint32 path_table_opt_be; + union { + l9660_dirent root_dir_ent; + char pad3[34]; + }; + char volume_set_id[128]; + char data_preparer_id[128]; + char app_id[128]; + char copyright_file[38]; + char abstract_file[36]; + char bibliography_file[37]; + l9660_desctime volume_created, + volume_modified, + volume_expires, + volume_effective; + uint8_t file_structure_version; + char pad4[1]; + char app_reserved[512]; + char reserved[653]; +} l9660_vdesc_primary; + +/* A generic volume descriptor (i.e. 2048 bytes) */ +typedef union { + l9660_vdesc_header hdr; + char _bits[2048]; +} l9660_vdesc; + +/* File system structure. + * Stick this inside your own structure and cast/offset as appropriate to store + * private data + */ +typedef struct l9660_fs { +#ifdef L9660_SINGLEBUFFER + union { + l9660_dirent root_dir_ent; + char root_dir_pad[34]; + }; +#else + /* Sector buffer to hold the PVD */ + l9660_vdesc pvd; +#endif + + /* read_sector func */ + bool (*read_sector)(struct l9660_fs *fs, void *buf, uint32_t sector); +} l9660_fs; + +typedef struct { +#ifndef L9660_SINGLEBUFFER + /* single sector buffer */ + char buf[2048]; +#endif + l9660_fs *fs; + uint32_t first_sector; + uint32_t position; + uint32_t length; +} l9660_file; + +typedef struct { + /* directories are mostly just files with special accessors, but we like type safetey */ + l9660_file file; +} l9660_dir; + +uint32_t l9660_tell(l9660_file *f); +l9660_status l9660_read(l9660_file *f, void *buf, size_t size, size_t *read); +l9660_status l9660_seek(l9660_file *f, int whence, int32_t offset); +l9660_status l9660_openat(l9660_file *child, l9660_dir *parent, const char *name); +l9660_status l9660_readdir(l9660_dir *dir, l9660_dirent **pdirent); +l9660_status l9660_opendirat(l9660_dir *dir, l9660_dir *parent, const char *path); +l9660_status l9660_fs_open_root(l9660_dir *dir, l9660_fs *fs); +l9660_status l9660_openfs(l9660_fs *fs, bool (*read_sector)(l9660_fs *fs, void *buf, uint32_t sector,uint8_t disk_number),uint8_t disk_number); +void init_iso9660(); + +#endif diff --git a/include/pcnet.h b/include/pcnet.h index d7b2ee6..5b7a608 100644 --- a/include/pcnet.h +++ b/include/pcnet.h @@ -28,7 +28,16 @@ #define RAP32 0x14 #define RESET32 0x18 #define BDP32 0x1c - +#define MTU 1500 +#define ARP_PROTOCOL 0x806 +#define IP_PROTOCOL 0x0800 +#define IP_MF 13 +#define IP_DF 14 +#define IP_OFFSET 0 +#define swap32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) +#define swap16(x) ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8)) #include #include "isr.h" @@ -58,5 +67,6 @@ int pcnet_find_card(); void init_pcnet_card(); void PCNET_IRQ(registers_t *reg); void Recv(); +void PcnetSend(uint8_t* buffer, int size); #endif diff --git a/include/timer.h b/include/timer.h index a20b5dc..465c1ca 100644 --- a/include/timer.h +++ b/include/timer.h @@ -27,6 +27,7 @@ void timer_free(struct TIMER *timer); void timer_init(struct TIMER *timer, struct FIFO8 *fifo, unsigned char data); void timer_settime(struct TIMER *timer, unsigned int timeout); void clock_sleep(uint32_t timer); +void sleep(uint32_t timer); struct TIMER *timer_alloc(void); unsigned int time(void); void init_pit(void); diff --git a/include/vdisk.h b/include/vdisk.h index 0f7cf01..fd0ec34 100644 --- a/include/vdisk.h +++ b/include/vdisk.h @@ -40,7 +40,7 @@ int rw_vdisk(char drive, unsigned int lba, unsigned char *buffer, int have_vdisk(char drive); void Disk_Read(unsigned int lba, unsigned int number, void *buffer, char drive); -int disk_Size(char drive); +unsigned int disk_Size(char drive); int DiskReady(char drive); void Disk_Write(unsigned int lba, unsigned int number, void *buffer, char drive); diff --git a/include/vfs.h b/include/vfs.h index ea5454d..4597cd0 100644 --- a/include/vfs.h +++ b/include/vfs.h @@ -50,6 +50,9 @@ typedef struct vfs_t { int flag; } vfs_t; +bool vfs_change_path(char *dictName); +void vfs_getPath(char *buffer); +void vfs_getPath_no_drive(char *buffer); bool vfs_mount_disk(uint8_t disk_number, uint8_t drive); bool vfs_unmount_disk(uint8_t drive); bool vfs_readfile(char *path, char *buffer); @@ -67,5 +70,6 @@ vfs_file *vfs_fileinfo(char *filename); bool vfs_change_disk(uint8_t drive); bool vfs_register_fs(vfs_t vfs); void init_vfs(); +vfs_file *get_cur_file(char* filename); #endif diff --git a/kernel/idt.c b/kernel/idt.c index 2231a32..5e94247 100644 --- a/kernel/idt.c +++ b/kernel/idt.c @@ -29,9 +29,10 @@ void isr_handler(registers_t regs) { } void irq_handler(registers_t regs) { - if (regs.int_no >= 40) outb(0xA0, 0x20); // 中断号 >= 40,来自从片,发送EOI给从片 - outb(0x20, 0x20); // 发送EOI给主片 - + if(regs.int_no != 0x2b) { + if (regs.int_no >= 40) outb(0xA0, 0x20); // 中断号 >= 40,来自从片,发送EOI给从片 + outb(0x20, 0x20); // 发送EOI给主片 + } if (interrupt_handlers[regs.int_no]) { isr_t handler = interrupt_handlers[regs.int_no]; // 有自定义处理程序,调用之 handler(®s); // 传入寄存器 diff --git a/kernel/kernel.c b/kernel/kernel.c index 02f2135..8037ddb 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -17,6 +17,8 @@ #include "../include/pcnet.h" #include "../include/ide.h" #include "../include/vfs.h" +#include "../include/fat.h" +#include "../include/iso9660.h" extern uint32_t end; extern int status; @@ -68,12 +70,20 @@ void kernel_main(multiboot_t *multiboot) { multiboot_all = multiboot; io_sti(); init_pit(); - init_vdisk(); init_pci(); - init_vfs(); + init_vdisk(); ide_initialize(0x1F0, 0x3F6, 0x170, 0x376, 0x000); + init_vfs(); + Register_fat_fileSys(); + init_iso9660(); syscall_install(); + vfs_mount_disk('A','A'); + if(vfs_change_disk('A')) + printf("[FileSystem]: Chang disk win!"); + else { + for(;;); + } if(pcnet_find_card()){ //init_pcnet_card(); } else printf("[\035kernel\036]: \033Cannot found pcnet.\036\n"); diff --git a/kernel/timer.c b/kernel/timer.c index 53921b8..a4316f7 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -22,6 +22,10 @@ static void timer_handle(registers_t *regs) { io_sti(); } +void sleep(uint32_t timer){ + clock_sleep(timer); +} + void clock_sleep(uint32_t timer){ uint32_t sleep = tick + timer; while(1){ diff --git a/network/arp.c b/network/arp.c index 9f883c5..e5100e8 100644 --- a/network/arp.c +++ b/network/arp.c @@ -1,7 +1,7 @@ #include "../include/arp.h" #include "../include/etherframe.h" #include "../include/memory.h" - +#include "../include/pcnet.h" uint8_t ARP_flags = 1; uint64_t ARP_mac_address[MAX_ARP_TABLE]; uint32_t ARP_ip_address[MAX_ARP_TABLE]; @@ -70,3 +70,40 @@ uint64_t IPParseMAC(uint32_t dstIP) { */ return ARP_mac_address[ARP_write_pointer - 1]; } +void arp_handler(void *base) { + extern uint32_t ip; + extern uint8_t mac0; + struct EthernetFrame_head *header = (struct EthernetFrame_head *)(base); + if ((*(uint64_t *)&header->dest_mac[0] & 0xffffffffffff) == + (*(uint64_t *)&mac0 & 0xffffffffffff)) { // ARP广播回应 + struct ARPMessage *arp = + (struct ARPMessage *)(base + sizeof(struct EthernetFrame_head)); + if (arp->command == 0x0200) { + // printk("ARP MAC Address Reply\n"); + if (ARP_write_pointer < MAX_ARP_TABLE) { + ARP_mac_address[ARP_write_pointer] = + *(uint64_t *)&header->src_mac[0] & 0xffffffffffff; + ARP_ip_address[ARP_write_pointer] = swap32(arp->src_ip); + ARP_write_pointer++; + ARP_flags = 0; + } + } + // 如果发送方不知道我们的MAC地址 + // 要发ARP数据包返回给发送方 告诉发送方我的MAC地址(确立联系) + } else if ((*(uint64_t *)&header->dest_mac[0] & 0xffffffffffff) == + 0xffffffffffff) { // dest_mac = 0xffffffffffff && ARP广播请求 + struct ARPMessage *arp = + (struct ARPMessage *)(base + sizeof(struct EthernetFrame_head)); + if (arp->command == 0x0100 && arp->dest_ip == swap32(ip)) { + // printk("ARP MAC Address request\n"); + uint32_t src_ip = ((arp->src_ip << 24) & 0xff000000) | + ((arp->src_ip << 8) & 0x00ff0000) | + ((arp->src_ip >> 8) & 0xff00) | + ((arp->src_ip >> 24) & 0xff); + ether_frame_provider_send(*(uint64_t *)&header->src_mac[0], 0x0806, + ARP_Packet(*(uint64_t *)&header->src_mac[0], + src_ip, *(uint64_t *)&mac0, ip, 2), + sizeof(struct ARPMessage)); + } + } +} \ No newline at end of file diff --git a/network/dhcp.c b/network/dhcp.c index baf6144..bafa604 100644 --- a/network/dhcp.c +++ b/network/dhcp.c @@ -65,6 +65,7 @@ int dhcp_discovery(uint8_t *mac) { } void dhcp_handler(void *base) { + printf("DHCP\n"); struct IPV4Message *ipv4 = (struct IPV4Message *)(base + sizeof(struct EthernetFrame_head)); struct UDPMessage *udp = @@ -74,9 +75,10 @@ void dhcp_handler(void *base) { (struct DHCPMessage *)(base + sizeof(struct EthernetFrame_head) + sizeof(struct IPV4Message) + sizeof(struct UDPMessage)); + printf("%d %d %d\n",dhcp->bp_options[0],dhcp->bp_options[1],dhcp->bp_options[2]); if (dhcp->bp_options[0] == 53 && dhcp->bp_options[1] == 1 && - dhcp->bp_options[2] == DHCP_OPTION_OFFER) { - // printk("DHCP Offer\n"); + dhcp->opcode == 2) { + printf("DHCP Offer\n"); ip = dhcp->yiaddr; uint8_t nip1 = ip; uint8_t nip2 = ip >> 8; @@ -86,22 +88,22 @@ void dhcp_handler(void *base) { // (uint8_t)(ipv4->srcIP >> 8), (uint8_t)(ipv4->srcIP >> 16), // (uint8_t)(ipv4->srcIP >> 24)); dhcp_ip = swap32(ipv4->srcIP); - //printk("IP: %d.%d.%d.%d\n", nip1, nip2, nip3, nip4); + printf("IP: %d.%d.%d.%d\n", nip1, nip2, nip3, nip4); ip = swap32(ip); unsigned char *options = &dhcp->bp_options[0]; while (options[0] != 0xff) { if (options[0] == MESSAGE_TYPE_DNS) { - // printk("DNS: %d.%d.%d.%d\n", options[2], options[3], options[4], - // options[5]); + printf("DNS: %d.%d.%d.%d\n", options[2], options[3], options[4], + options[5]); dns = swap32(*(uint32_t *)&options[2]); } else if (options[0] == MESSAGE_TYPE_REQ_SUBNET_MASK) { - // printk("Subnet Mask: %d.%d.%d.%d\n", options[2], options[3], options[4], - // options[5]); + printf("Subnet Mask: %d.%d.%d.%d\n", options[2], options[3], options[4], + options[5]); submask = swap32(*(uint32_t *)&options[2]); } else if (options[0] == MESSAGE_TYPE_ROUTER) { - // printk("Gateway: %d.%d.%d.%d\n", options[2], options[3], options[4], - // options[5]); + printf("Gateway: %d.%d.%d.%d\n", options[2], options[3], options[4], + options[5]); gateway = swap32(*(uint32_t *)&options[2]); } options += options[1] + 2; diff --git a/network/etherframe.c b/network/etherframe.c index 172c765..208bd2a 100644 --- a/network/etherframe.c +++ b/network/etherframe.c @@ -1,7 +1,7 @@ #include "../include/etherframe.h" #include "../include/memory.h" #include "../include/net.h" - +#include "../include/pcnet.h" extern uint8_t mac0, mac1, mac2, mac3, mac4, mac5; // 以太网帧 void ether_frame_provider_send(uint64_t dest_mac, uint16_t type, uint8_t *buffer, @@ -31,7 +31,7 @@ void ether_frame_provider_send(uint64_t dest_mac, uint16_t type, uint8_t *buffer uint8_t *dst = buffer2 + sizeof(struct EthernetFrame_head); for (uint32_t i = 0; i < size; i++) dst[i] = src[i]; - netcard_send(buffer2, sizeof(struct EthernetFrame_head) + size + + PcnetSend(buffer2, sizeof(struct EthernetFrame_head) + size + sizeof(struct EthernetFrame_tail)); kfree(buffer2); } diff --git a/network/pcnet.c b/network/pcnet.c index 318eda2..36c1b7a 100644 --- a/network/pcnet.c +++ b/network/pcnet.c @@ -6,6 +6,11 @@ #include "../include/memory.h" #include "../include/printf.h" #include "../include/dhcp.h" +#include "../include/etherframe.h" +#include "../include/arp.h" +#include "../include/ipv4.h" +#include "../include/tcp.h" +#include "../include/udp.h" uint8_t bus = 255, dev = 255, func = 255; @@ -25,7 +30,9 @@ struct InitializationBlock initBlock; static struct BufferDescriptor* sendBufferDesc; static struct BufferDescriptor* recvBufferDesc; int recv = 0; - +static uint8_t* IP_Packet_Base[16] = {NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL}; static void set_handler(int IRQ, int addr) { register_interrupt_handler(0x20 + IRQ, (int)addr); } @@ -61,7 +68,6 @@ void Activate() { printf("[pcnet]: io\n"); io_out16(io_base + RDP16, 0x41); printf("[pcnet]: success.\n"); - io_out16(io_base + RAP16, CSR4); uint32_t temp = io_in16(io_base + RDP16); io_out16(io_base + RAP16, CSR4); @@ -91,7 +97,9 @@ static void init_Card_all() { mac4 = io_in8(io_base + APROM4); mac5 = io_in8(io_base + APROM5); reset_card(); + printf("SLEEP\n"); clock_sleep(1); + printf("END\n"); @@ -148,6 +156,7 @@ static void init_Card_all() { gateway = 0xFFFFFFFF; submask = 0xFFFFFFFF; dns = 0xFFFFFFFF; + printf("DHCP DISCOVERY %08x %08x %08x %08x %08x %08x\n",&mac0,&mac1,&mac2,&mac3,&mac4,&mac5); dhcp_discovery(&mac0); while (gateway == 0xFFFFFFFF && submask == 0xFFFFFFFF && dns == 0xFFFFFFFF && ip == 0xFFFFFFFF) { @@ -156,8 +165,8 @@ static void init_Card_all() { } void init_pcnet_card() { - printf("[\035kernel\036]: Loading pcnet driver.\n"); - register_interrupt_handler(pci_get_drive_irq(bus, dev, func),PCNET_IRQ); + printf("[\035kernel\036]: Loading pcnet driver. %x\n",pci_get_drive_irq(bus, dev, func)); + register_interrupt_handler(pci_get_drive_irq(bus, dev, func) + 0x20,PCNET_IRQ); // 2,写COMMAND和STATUS寄存器 uint32_t conf = pci_read_command_status(bus, dev, func); conf &= 0xffff0000; // 保留STATUS寄存器,清除COMMAND寄存器 @@ -170,7 +179,7 @@ void init_pcnet_card() { } void PCNET_IRQ(registers_t *reg) { - + printf("PCNET IRQ"); io_out16(io_base + RAP16, CSR0); uint16_t temp = io_in16(io_base + RDP16); @@ -182,12 +191,91 @@ void PCNET_IRQ(registers_t *reg) { if ((temp & 0x0100) == 0x0100) printf("PCNET INIT DONE\n"); + io_out8(0xa0, (0x60 + pci_get_drive_irq(bus, dev, func) - 0x8)); + io_out8(0x20, 0x62); return; } +static uint32_t Find_IP_Packet(uint16_t ident) { + for (int i = 0; i != 16; i++) { + if (IP_Packet_Base[i] != NULL) { + struct IPV4Message* ipv4 = + (struct IPV4Message*)(IP_Packet_Base[i] + + sizeof(struct EthernetFrame_head)); + if (swap16(ipv4->ident) == ident) { + return i; + } + } + } + return -1; +} +static void IP_Assembling(struct IPV4Message* ipv4, unsigned char* RawData) { + uint32_t i_p = Find_IP_Packet(swap16(ipv4->ident)); + struct IPV4Message* ipv4_p = + (struct IPV4Message*)(IP_Packet_Base[i_p] + + sizeof(struct EthernetFrame_head)); + uint32_t size_p = swap16(ipv4_p->totalLength); + ipv4_p->totalLength = + swap16(swap16(ipv4->totalLength) + swap16(ipv4_p->totalLength) - + sizeof(struct IPV4Message)); + IP_Packet_Base[i_p] = (uint8_t*)realloc((void*)IP_Packet_Base[i_p], + swap16(ipv4_p->totalLength)); + memcpy( + (void*)(IP_Packet_Base[i_p] + size_p), + RawData + sizeof(struct EthernetFrame_head) + sizeof(struct IPV4Message), + swap16(ipv4->totalLength) - sizeof(struct IPV4Message)); + return; +} +void Card_Recv_Handler(unsigned char* RawData) { + struct EthernetFrame_head* header = (struct EthernetFrame_head*)(RawData); + if (header->type == swap16(IP_PROTOCOL)) { // IP数据报 + struct IPV4Message* ipv4 = + (struct IPV4Message*)(RawData + sizeof(struct EthernetFrame_head)); + if (ipv4->version == 4) { + if ((swap16(ipv4->flagsAndOffset) >> IP_MF) & 1) { + if (Find_IP_Packet(swap16(ipv4->ident)) == -1) { + for (int i = 0; i != 16; i++) { + if (IP_Packet_Base[i] == NULL) { + IP_Packet_Base[i] = + (uint8_t*)kmalloc(swap16(ipv4->totalLength) + + sizeof(struct EthernetFrame_head)); + memcpy((void*)IP_Packet_Base[i], RawData, + swap16(ipv4->totalLength) + + sizeof(struct EthernetFrame_head)); + break; + } + } + } else { + IP_Assembling(ipv4, RawData); + } + } else if (!((swap16(ipv4->flagsAndOffset) >> IP_MF) & 1)) { + uint32_t i_p = Find_IP_Packet(swap16(ipv4->ident)); + void* base = RawData; + if (i_p != -1) { + IP_Assembling(ipv4, RawData); + base = (void*)IP_Packet_Base[i_p]; + } + // if (ipv4->protocol == ICMP_PROTOCOL) { // ICMP + // icmp_handler(base); + /*} else*/ if (ipv4->protocol == UDP_PROTOCOL) { // UDP + printf("UDP\n"); + udp_handler(base); + } else if (ipv4->protocol == TCP_PROTOCOL) { // TCP + tcp_handler(base); + } + if (i_p != -1) { + kfree((void*)IP_Packet_Base[i_p]); + IP_Packet_Base[i_p] = NULL; + } + } + } + } else if (header->type == swap16(ARP_PROTOCOL)) { // ARP + arp_handler(RawData); + } +} void Recv() { recv = 1; - //printk("\nPCNET RECV: "); + printk("\nPCNET RECV: "); for (; (recvBufferDesc[currentRecvBuffer].flags & 0x80000000) == 0; currentRecvBuffer = (currentRecvBuffer + 1) % 8) { if (!(recvBufferDesc[currentRecvBuffer].flags & 0x40000000) && @@ -204,7 +292,7 @@ void Recv() { } recv = 0; currentRecvBuffer = 0; - //TODO Card_Recv_Handler(recvBufferDesc[currentRecvBuffer].address); + Card_Recv_Handler(recvBufferDesc[currentRecvBuffer].address); memclean(recvBufferDesc[currentRecvBuffer].address, 2048); recvBufferDesc[currentRecvBuffer].flags2 = 0; @@ -214,3 +302,32 @@ void Recv() { } +void PcnetSend(uint8_t* buffer, int size) { + while(recv); + int sendDesc = currentSendBuffer; + currentSendBuffer = (currentSendBuffer + 1) % 8; + memclean(sendBufferDesc[currentSendBuffer].address, 2048); + if (size > MTU + sizeof(struct EthernetFrame_head) + + sizeof(struct EthernetFrame_tail)) + size = MTU + sizeof(struct EthernetFrame_head) + + sizeof(struct EthernetFrame_tail); + + for (uint8_t *src = buffer + size - 1, + *dst = (uint8_t*)(sendBufferDesc[sendDesc].address + size - 1); + src >= buffer; src--, dst--) + *dst = *src; + + //printk("SENDING: "); + for (int i = 0; i < (size > 128 ? 128 : size); i++) { + //printk("%02x ", buffer[i]); + } + //printk("\n"); + sendBufferDesc[sendDesc].avail = 0; + sendBufferDesc[sendDesc].flags = 0x8300f000 | ((uint16_t)((-size) & 0xfff)); + sendBufferDesc[sendDesc].flags2 = 0; + + io_out16(io_base + RAP16, CSR0); + io_out16(io_base + RDP16, 0x48); + + currentSendBuffer = 0; +} \ No newline at end of file diff --git a/sysapp/shell.c b/sysapp/shell.c index 6f488db..d7f37e8 100644 --- a/sysapp/shell.c +++ b/sysapp/shell.c @@ -5,6 +5,7 @@ #include "../include/task.h" #include "../include/cmos.h" #include "../include/vdisk.h" +#include "../include/vfs.h" extern Queue *key_char_queue; extern vdisk vdisk_ctl[10]; @@ -66,36 +67,62 @@ void cmd_echo(int argc, char **argv) { vga_putchar('\n'); } -void cmd_proc(int argc, char **argv){ +void cmd_proc(int argc, char **argv) { if (argc <= 1) { printf("\033[Shell-PROC]: If there are too few parameters.\036\n"); return; } - if(!strcmp("list",argv[1])){ + if (!strcmp("list", argv[1])) { print_proc(); - } else if(!strcmp("kill",argv[1])){ + } else if (!strcmp("kill", argv[1])) { if (argc <= 2) { printf("\033[Shell-PROC-kill]: If there are too few parameters.\036\n"); return; } - int pid = strtol(argv[2],NULL,10); + int pid = strtol(argv[2], NULL, 10); task_kill(pid); - } else{ + } else { printf("\033[Shell-[PROC]]: Unknown parameter\036\n"); return; } } -void cmd_date(){ - printf("System Time: %s\n",get_date_time()); - printf("Memory Usage: [%dKB] | All Size: [%dMB]\n",memory_usage()/1024,(KHEAP_START+KHEAP_INITIAL_SIZE)/1024/1024); +void cmd_date() { + printf("System Time: %s\n", get_date_time()); + printf("Memory Usage: [%dKB] | All Size: [%dMB]\n", memory_usage() / 1024, + (KHEAP_START + KHEAP_INITIAL_SIZE) / 1024 / 1024); print_cpu_id(); + vga_writestring("\n"); } void cmd_ls() { + List *ls = vfs_listfile(""); + int files = 0, dirs = 0; + for (int i = 1; FindForCount(i, ls) != NULL; i++) { + vfs_file *d = (vfs_file *) FindForCount(i, ls)->val; + char *type; + if (d->type == DIR) { + type = ""; //文件夹 + dirs++; + } else if (d->type == HID) { + type = ""; //隐藏文件 + files++; + } else { + type = ""; //文件 + files++; + } + printf("%-13s %-6s %d \n", d->name, type, d->size / 1024); + kfree(d); + } + printf("-----------------------------------------\n"); + printf("Name Type Size(KB)\n" + "All directory: %d | All Files: %d\n",dirs, files); + + DeleteList(ls); + kfree(ls); } void cmd_mkdir(int argc, char **argv) { @@ -103,8 +130,17 @@ void cmd_mkdir(int argc, char **argv) { printf("\033[Shell-MKDIR]: If there are too few parameters, please specify the directory name.\036\n"); return; } - printf("Create directory: %s\n",argv[1]); + vfs_file *file = get_cur_file(argv[1]); + + if(file != NULL){ + printf("This file is exist.\n"); + return; + } + + if(!vfs_createdict(argv[1])){ + printf("Illegal create.\n"); + } else printf("Create directory: %s\n", argv[1]); } void cmd_del(int argc, char **argv) { @@ -113,62 +149,85 @@ void cmd_del(int argc, char **argv) { return; } + vfs_file *file = get_cur_file(argv[1]); + + if(file == NULL){ + printf("Cannot found file.\n"); + return; + } + + bool b; + if(file->type == DIR){ + b = vfs_deldir(argv[1]); + } else b = vfs_delfile(argv[1]); + if(!b){ + printf("Illegal delete!\n"); + } } -void cmd_reset(){ +void cmd_reset() { reset_kernel(); } -void cmd_shutdown(){ +void cmd_shutdown() { shutdown_kernel(); } -void cmd_debug(){ +void cmd_debug() { vga_clear(); - printf("%s for x86 [Version %s] \n",OS_NAME, OS_VERSION); + printf("%s for x86 [Version %s] \n", OS_NAME, OS_VERSION); printf("\032Copyright 2024 XIAOYI12 (Build by GCC i686-elf-tools)\036\n"); extern int acpi_enable_flag; extern uint8_t *rsdp_address; - printf("ACPI: Enable: %s | RSDP Address: 0x%08x\n",acpi_enable_flag?"\035ENABLE\036":"\033DISABLE\036",rsdp_address); + printf("ACPI: Enable: %s | RSDP Address: 0x%08x\n", acpi_enable_flag ? "\035ENABLE\036" : "\033DISABLE\036", + rsdp_address); int index = 0; - print_proc_t(&index,get_current(),get_current()->next,0); - printf("Process Runnable: %d\n",index); + print_proc_t(&index, get_current(), get_current()->next, 0); + printf("Process Runnable: %d\n", index); cmd_date(); for (int i = 0; i < 10; i++) { if (vdisk_ctl[i].flag) { vdisk vd = vdisk_ctl[i]; char id = i + ('A'); - printf("[DISK-%c]: Size: %dMB | Name: %s\n",id,vd.size,vd.DriveName); + printf("[DISK-%c]: Size: %dMB | Name: %s\n", id, vd.size, vd.DriveName); } } printf(" > > > > ====[Registers Info]==== < < < <\n"); register uint32_t eax asm("eax"), - ecx asm("ecx"), - esp asm("esp"), - ebp asm("ebp"), - ebx asm("ebx"), - esi asm("esi"), - edi asm("edi"); - printf("EAX: 0x%08x | EBX 0x%08x | ECX 0x%08x | ESP 0x%08x \n",eax,ebx,ecx,esp); - printf("ESI: 0x%08x | EDI 0x%08x | EBP 0x%08x | EFLAGS 0x%08x\n",esi,edi,ebp,get_current()->context.eflags); + ecx asm("ecx"), + esp asm("esp"), + ebp asm("ebp"), + ebx asm("ebx"), + esi asm("esi"), + edi asm("edi"); + printf("EAX: 0x%08x | EBX 0x%08x | ECX 0x%08x | ESP 0x%08x \n", eax, ebx, ecx, esp); + printf("ESI: 0x%08x | EDI 0x%08x | EBP 0x%08x | EFLAGS 0x%08x\n", esi, edi, ebp, get_current()->context.eflags); } -void cmd_disk(int argc,char **argv){ - if(argc > 1){ - if(!strcmp("list",argv[1])){ +void cmd_cd(int argc, char **argv) { + if (argc == 1) { + vga_writestring("\033[Shell-CD]: If there are too few parameters, please specify the path.\036\n"); + return; + } + if (vfs_change_path(argv[1]) == 0) printf("Invalid path.\n"); +} + +void cmd_disk(int argc, char **argv) { + if (argc > 1) { + if (!strcmp("list", argv[1])) { printf("[Disk]: Loaded disk - "); for (int i = 0; i < 10; i++) { if (vdisk_ctl[i].flag) { vdisk vd = vdisk_ctl[i]; char id = i + ('A'); - printf("(%c) ",id,vd.size,vd.DriveName); + printf("(%c) ", id, vd.size, vd.DriveName); } } printf("\n"); return; } - if(strlen(argv[1]) > 1){ + if (strlen(argv[1]) > 1) { printf("\033[DISK]: Cannot found disk.\036\n"); return; } @@ -177,12 +236,12 @@ void cmd_disk(int argc,char **argv){ if (vdisk_ctl[i].flag) { vdisk vd = vdisk_ctl[i]; char id = i + ('A'); - if(id == (argv[1][0])){ + if (id == (argv[1][0])) { printf("[Disk(%c)]: \n" " Size: %dMB\n" " Name: %s\n" " WriteAddress: 0x%08x\n" - " ReadAddress: 0x%08x\n",id,vd.size,vd.DriveName,vd.Write,vd.Read); + " ReadAddress: 0x%08x\n", id, vd.size, vd.DriveName, vd.Write, vd.Read); return; } } @@ -195,46 +254,48 @@ void cmd_disk(int argc,char **argv){ if (vdisk_ctl[i].flag) { vdisk vd = vdisk_ctl[i]; char id = i + ('A'); - printf("(%c) ",id,vd.size,vd.DriveName); + printf("(%c) ", id, vd.size, vd.DriveName); } } printf("\n"); } -char* user(){ +char *user() { printf("\n\nPlease type your username and password.\n"); char com[MAX_COMMAND_LEN]; - char* username = "admin"; - char* password = "12345678"; - while (1){ + char *username = "admin"; + char *password = "12345678"; + while (1) { print("username/> "); if (gets(com, MAX_COMMAND_LEN) <= 0) continue; - if(!strcmp(username,com)){ + if (!strcmp(username, com)) { break; } else printf("Cannot found username, Please check your info.\n"); } - while (1){ + while (1) { print("password/> "); if (gets(com, MAX_COMMAND_LEN) <= 0) continue; - if(!strcmp(password,com)){ + if (!strcmp(password, com)) { break; } else printf("Unknown password, Please check your info.\n"); } return username; } -void setup_shell(){ - char* user1 = user(); +void setup_shell() { + char *user1 = "default";//user(); vga_clear(); - printf("%s for x86 [Version %s] \n",OS_NAME, OS_VERSION); + printf("%s for x86 [Version %s] \n", OS_NAME, OS_VERSION); printf("\032Copyright 2024 XIAOYI12 (Build by GCC i686-elf-tools)\036\n"); char com[MAX_COMMAND_LEN]; char *argv[MAX_ARG_NR]; int argc = -1; + char *buffer[255]; while (1) { - printf("\035%s/>\036 ",user1); + vfs_getPath(buffer); + printf("\035%s %s\\>\036 ", user1, buffer); if (gets(com, MAX_COMMAND_LEN) <= 0) continue; argc = cmd_parse(com, argv, ' '); @@ -244,7 +305,7 @@ void setup_shell(){ } if (!strcmp("version", argv[0])) - printf("%s for x86 [%s]\n",OS_NAME, OS_VERSION); + printf("%s for x86 [%s]\n", OS_NAME, OS_VERSION); else if (!strcmp("echo", argv[0])) cmd_echo(argc, argv); else if (!strcmp("clear", argv[0])) @@ -261,12 +322,14 @@ void setup_shell(){ cmd_del(argc, argv); else if (!strcmp("reset", argv[0])) cmd_reset(); - else if (!strcmp("shutdown", argv[0])||!strcmp("exit", argv[0])) + else if (!strcmp("shutdown", argv[0]) || !strcmp("exit", argv[0])) cmd_shutdown(); else if (!strcmp("debug", argv[0])) cmd_debug(); else if (!strcmp("disk", argv[0])) - cmd_disk(argc,argv); + cmd_disk(argc, argv); + else if (!strcmp("cd", argv[0])) + cmd_cd(argc, argv); else if (!strcmp("help", argv[0]) || !strcmp("?", argv[0]) || !strcmp("h", argv[0])) { vga_writestring("-=[\037CoolPotShell Helper\036]=-\n"); vga_writestring("help ? h \032Print shell help info.\036\n"); @@ -281,6 +344,7 @@ void setup_shell(){ vga_writestring("shutdown exit \032Shutdown OS.\036\n"); vga_writestring("debug \032Print os debug info.\036\n"); vga_writestring("disk [list|] \032List or view disks.\036\n"); + vga_writestring("cd \032Change shell top directory.\036\n"); } else printf("\033[Shell]: Unknown command '%s'.\036\n", argv[0]); } } diff --git a/util/common.c b/util/common.c index 6ffa4fd..e992997 100644 --- a/util/common.c +++ b/util/common.c @@ -152,6 +152,7 @@ char *strcpy(char *dest, const char *src) { do { *dest++ = *src++; } while (*src != 0); + *dest = 0; } char *strcat(char *dest, const char *src) { @@ -477,14 +478,10 @@ char *uint32_to_str_oct(uint32_t num, int flag, int width) { return str_first; } -char *insert_str(char *buf, const char *str) { - char *p = buf; - - while (*str) { - *p++ = *str++; +void insert_str(char *str, char *insert_str, int pos) { + for (int i = 0; i < strlen(insert_str); i++) { + insert_char(str, pos + i, insert_str[i]); } - - return p; } void assert(int b, char *message) {