PUBLIC void task_fs() { printl("Task FS begins.\n"); init_fs(); while (1) { send_recv(RECEIVE, ANY, &fs_msg); int src = fs_msg.source; pcaller = &proc_table[src]; switch (fs_msg.type) { case OPEN: fs_msg.FD = do_open(); break; case CLOSE: fs_msg.RETVAL = do_close(); break; case READ: case WRITE: fs_msg.CNT = do_rdwt(); break; case UNLINK: fs_msg.RETVAL = do_unlink(); break; case RESUME_PROC: src = fs_msg.PROC_NR; // 恢复最初请求的进程,如 TestB break; case FORK: fs_msg.RETVAL = fs_fork(); break; case EXIT: fs_msg.RETVAL = fs_exit(); break; case STAT: fs_msg.RETVAL = do_stat(); break; default: dump_msg("FS::unknown message:", &fs_msg); assert(0); break; } /* 如果发送者要求挂起,则不回送消息 */ if (fs_msg.type != SUSPEND_PROC) { fs_msg.type = SYSCALL_RET; send_recv(SEND, src, &fs_msg); } } spin("FS"); }
/** * <Ring 1> Make a available Orange'S FS in the disk. It will * - Write a super block to sector 1. * - Create three special files: dev_tty0, dev_tty1, dev_tty2 * - Create the inode map * - Create the sector map * - Create the inodes of the files * - Create `/', the root directory *****************************************************************************/ PRIVATE void mkfs() { MESSAGE driver_msg; int i, j; int bits_per_sect = SECTOR_SIZE * 8; /* 8 bits per byte */ /* get the geometry of ROOTDEV */ struct part_info geo; driver_msg.type = DEV_IOCTL; driver_msg.DEVICE = MINOR(ROOT_DEV); driver_msg.REQUEST = DIOCTL_GET_GEO; driver_msg.BUF = &geo; driver_msg.PROC_NR = TASK_FS; assert(dd_map[MAJOR(ROOT_DEV)].driver_nr != INVALID_DRIVER); send_recv(BOTH, dd_map[MAJOR(ROOT_DEV)].driver_nr, &driver_msg); printl("dev size: 0x%x sectors\n", geo.size); /************************/ /* super block */ /************************/ struct super_block sb; sb.magic = MAGIC_V1; sb.nr_inodes = bits_per_sect; sb.nr_inode_sects = sb.nr_inodes * INODE_SIZE / SECTOR_SIZE; sb.nr_sects = geo.size; /* partition size in sector */ sb.nr_imap_sects = 1; sb.nr_smap_sects = sb.nr_sects / bits_per_sect + 1; sb.n_1st_sect = 1 + 1 + /* boot sector & super block */ sb.nr_imap_sects + sb.nr_smap_sects + sb.nr_inode_sects; sb.root_inode = ROOT_INODE; sb.inode_size = INODE_SIZE; struct inode x; sb.inode_isize_off= (int)&x.i_size - (int)&x; sb.inode_start_off= (int)&x.i_start_sect - (int)&x; sb.dir_ent_size = DIR_ENTRY_SIZE; struct dir_entry de; sb.dir_ent_inode_off = (int)&de.inode_nr - (int)&de; sb.dir_ent_fname_off = (int)&de.name - (int)&de; memset(fsbuf, 0x90, SECTOR_SIZE); memcpy(fsbuf, &sb, SUPER_BLOCK_SIZE); /* write the super block */ WR_SECT(ROOT_DEV, 1); printl("devbase:0x%x00, sb:0x%x00, imap:0x%x00, smap:0x%x00\n" " inodes:0x%x00, 1st_sector:0x%x00\n", geo.base * 2, (geo.base + 1) * 2, (geo.base + 1 + 1) * 2, (geo.base + 1 + 1 + sb.nr_imap_sects) * 2, (geo.base + 1 + 1 + sb.nr_imap_sects + sb.nr_smap_sects) * 2, (geo.base + sb.n_1st_sect) * 2); /************************/ /* inode map */ /************************/ memset(fsbuf, 0, SECTOR_SIZE); for (i = 0; i < (NR_CONSOLES + 2); i++) fsbuf[0] |= 1 << i; assert(fsbuf[0] == 0x1F);/* 0001 1111 : * | |||| * | |||`--- bit 0 : reserved * | ||`---- bit 1 : the first inode, * | || which indicates `/' * | |`----- bit 2 : /dev_tty0 * | `------ bit 3 : /dev_tty1 * `-------- bit 4 : /dev_tty2 */ WR_SECT(ROOT_DEV, 2); /************************/ /* secter map */ /************************/ memset(fsbuf, 0, SECTOR_SIZE); int nr_sects = NR_DEFAULT_FILE_SECTS + 1; /* ~~~~~~~~~~~~~~~~~~~|~ | * | `--- bit 0 is reserved * `-------- for `/' */ for (i = 0; i < nr_sects / 8; i++) fsbuf[i] = 0xFF; for (j = 0; j < nr_sects % 8; j++) fsbuf[i] |= (1 << j); WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects); /* zeromemory the rest sector-map */ memset(fsbuf, 0, SECTOR_SIZE); for (i = 1; i < sb.nr_smap_sects; i++) WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + i); /************************/ /* inodes */ /************************/ /* inode of `/' */ memset(fsbuf, 0, SECTOR_SIZE); struct inode * pi = (struct inode*)fsbuf; pi->i_mode = I_DIRECTORY; pi->i_size = DIR_ENTRY_SIZE * 4; /* 4 files: * `.', * `dev_tty0', `dev_tty1', `dev_tty2', */ pi->i_start_sect = sb.n_1st_sect; pi->i_nr_sects = NR_DEFAULT_FILE_SECTS; /* inode of `/dev_tty0~2' */ for (i = 0; i < NR_CONSOLES; i++) { pi = (struct inode*)(fsbuf + (INODE_SIZE * (i + 1))); pi->i_mode = I_CHAR_SPECIAL; pi->i_size = 0; pi->i_start_sect = MAKE_DEV(DEV_CHAR_TTY, i); pi->i_nr_sects = 0; } WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + sb.nr_smap_sects); /************************/ /* `/' */ /************************/ memset(fsbuf, 0, SECTOR_SIZE); struct dir_entry * pde = (struct dir_entry *)fsbuf; pde->inode_nr = 1; strcpy(pde->name, "."); /* dir entries of `/dev_tty0~2' */ for (i = 0; i < NR_CONSOLES; i++) { pde++; pde->inode_nr = i + 2; /* dev_tty0's inode_nr is 2 */ sprintf(pde->name, "dev_tty%d", i); } WR_SECT(ROOT_DEV, sb.n_1st_sect); }
int cbuf_create(spdid_t spdid, unsigned long size, int cbid) { struct cbuf_comp_info *cci; struct cbuf_info *cbi; struct cbuf_meta *meta; struct cbuf_bin *bin; int ret = 0; unsigned int id = (unsigned int)cbid; printl("cbuf_create\n"); if (unlikely(cbid < 0)) return 0; CBUF_TAKE(); tracking_start(NULL, CBUF_CRT); cci = cbuf_comp_info_get(spdid); if (unlikely(!cci)) goto done; /* * Client wants to allocate a new cbuf, but the meta might not * be mapped in. */ if (!cbid) { /* TODO: check if have enough free memory: ask mem manager */ /*memory usage exceeds the target, block this thread*/ if (size + cci->allocated_size > cci->target_size) { cbuf_shrink(cci, size); if (size + cci->allocated_size > cci->target_size) { cbuf_thread_block(cci, size); return 0; } } cbi = malloc(sizeof(struct cbuf_info)); if (unlikely(!cbi)) goto done; /* Allocate and map in the cbuf. Discard inconsistent cbufs */ /* TODO: Find a better way to manage those inconsistent cbufs */ do { id = cmap_add(&cbufs, cbi); meta = cbuf_meta_lookup(cci, id); } while(meta && CBUF_INCONSISENT(meta)); cbi->cbid = id; size = round_up_to_page(size); cbi->size = size; cbi->owner.m = NULL; cbi->owner.spdid = spdid; INIT_LIST(&cbi->owner, next, prev); INIT_LIST(cbi, next, prev); if (cbuf_alloc_map(spdid, &(cbi->owner.addr), (void**)&(cbi->mem), NULL, size, MAPPING_RW)) { goto free; } } /* If the client has a cbid, then make sure we agree! */ else { cbi = cmap_lookup(&cbufs, id); if (unlikely(!cbi)) goto done; if (unlikely(cbi->owner.spdid != spdid)) goto done; } meta = cbuf_meta_lookup(cci, id); /* We need to map in the meta for this cbid. Tell the client. */ if (!meta) { ret = (int)id * -1; goto done; } /* * Now we know we have a cbid, a backing structure for it, a * component structure, and the meta mapped in for the cbuf. * Update the meta with the correct addresses and flags! */ memset(meta, 0, sizeof(struct cbuf_meta)); meta->sz = cbi->size >> PAGE_ORDER; meta->cbid_tag.cbid = id; CBUF_FLAG_ADD(meta, CBUF_OWNER); CBUF_PTR_SET(meta, cbi->owner.addr); CBUF_REFCNT_INC(meta); /* * When creates a new cbuf, the manager should be the only * one who can access the meta */ /* TODO: malicious client may trigger this assertion, just for debug */ assert(CBUF_REFCNT(meta) == 1); assert(CBUF_PTR(meta)); cbi->owner.m = meta; /* * Install cbi last. If not, after return a negative cbid, * collection may happen and get a dangle cbi */ bin = cbuf_comp_info_bin_get(cci, size); if (!bin) bin = cbuf_comp_info_bin_add(cci, size); if (unlikely(!bin)) goto free; if (bin->c) ADD_LIST(bin->c, cbi, next, prev); else bin->c = cbi; cci->allocated_size += size; ret = (int)id; done: tracking_end(NULL, CBUF_CRT); CBUF_RELEASE(); return ret; free: cmap_del(&cbufs, id); free(cbi); goto done; }
PUBLIC void task_fs() { init_buffer(); printl("VFS: VFS is running.\n"); MESSAGE msg; struct file_system * fs; while (1){ send_recv(RECEIVE, ANY, &msg); int src = msg.source; pcaller = &proc_table[src]; int msgtype = msg.type; fs = file_systems; switch (msgtype) { case FS_REGISTER: register_filesystem(&msg); break; case OPEN: printl("Doing open, %d\n", fs->open); msg.FD = fs->open(&msg); printl("Done open, %d\n", fs->open); break; case CLOSE: msg.RETVAL = fs->close(&msg); break; case READ: case WRITE: msg.CNT = fs->rdwt(&msg); break; case UNLINK: msg.RETVAL = fs->unlink(&msg); break; case MOUNT: msg.RETVAL = fs->mount(&msg); break; case UMOUNT: msg.RETVAL = fs->umount(&msg); break; case MKDIR: msg.RETVAL = fs->mkdir(&msg); break; case RESUME_PROC: src = msg.PROC_NR; break; case FORK: msg.RETVAL = fs->fork(&msg); break; case EXIT: msg.RETVAL = fs->exit(&msg); break; case LSEEK: msg.OFFSET = fs->lseek(&msg); break; case STAT: msg.RETVAL = fs->stat(&msg); break; case CHROOT: msg.RETVAL = fs->chroot(&msg); break; case CHDIR: msg.RETVAL = fs->chdir(&msg); break; default: dump_msg("VFS: Unknown message:", &msg); assert(0); break; } /* reply */ if (msg.type != SUSPEND_PROC) { msg.type = SYSCALL_RET; send_recv(SEND, src, &msg); } } }
program() { printl(listfiles().convert(FM,"\n")); }
static int do_open(MESSAGE *message){ int i,fd=-1; const char *path; char dirname[MAX_FILENAME_LENGTH]={0}; char filename[MAX_FILENAME_LENGTH]={0}; int flags; int inode_index; struct s_file_descriptor *pfd=NULL; struct s_inode *pinode=NULL; /* struct s_inode parent_dir_inode; */ PROCESS *process; path=message->arg_pointer; flags=message->flags; process=pid2process(message->source_pid); pfd=get_free_fd_from_table(); pinode=get_free_inode_from_table(); if(pfd==NULL || pinode==NULL){ set_error_index(NO_FD_INODE); return -1; } //分离父目录路径和文件名 if(!strip_path(path,dirname,filename)){ return -1; } #ifdef DEBUG_FS printl("dir_name=%s file_name=%s\n",dirname,filename); #endif //搜索文件 inode_index=search_file(dirname,filename,GET_FILE_TYPE(flags)); if(inode_index<0){ if((flags & O_CREATE)==0){ return -1; } inode_index=create_file(dirname,filename,GET_FILE_TYPE(flags)); if(inode_index<0){ return -1; } } assert(inode_index>=0,""); get_inode_by_index(inode_index,pinode); #ifdef DEBUG_FS printl("pinode.start_index=%d(in do_open)",pinode->i_start_sector_index); #endif /*SDTIN=0,STDOUT=1,STDERROR=2*/ for(i=3;i<FILE_COUNT;i++){ if(process->file_descriptor[i]==NULL){ fd=i; break; } } if(fd>=0){ process->file_descriptor[fd]=pfd; pfd->fd_inode=pinode; pfd->fd_op_mode=GET_FILE_OP(flags); pfd->fd_position=0; pinode->i_inode_index=inode_index; #ifdef DEBUG_FS printl("inode_index=%d(in do_open)\n",pinode->i_inode_index); printl("data_sector_index=%d data_sector_length=%d\n",process->file_descriptor[fd]->fd_inode->i_start_sector_index,process->file_descriptor[fd]->fd_inode->i_sectors_length); #endif return fd; }else{ set_error_index(PROCESS_FD_POINTER_NOT_ENOUGH); return -1; } }
static void free_smap_bit(int bits_index,int bits_length){ assert(bits_length==1,"only for sector_length=1 currently!"); #ifdef DEBUG_FS printl("bits_index=%d bits_length=%d(int free_smap_bit)\n",bits_index,bits_length); #endif u8 fsbuf[SECTOR_SIZE]; int sector_index,sector_length,bits_off, bytes_index,bytes_start,bytes_end; sector_index=get_smap_first_index(super_block)+bits_index/BITS_PER_SECTOR; sector_length=(bits_index+bits_length+BITS_PER_SECTOR-1)/BITS_PER_SECTOR; bits_off=bits_index%BITS_PER_SECTOR; bytes_start=(bits_off+BITS_PER_BYTE-1)/BITS_PER_BYTE; bytes_end=(bits_off+bits_length)/BITS_PER_BYTE; #ifdef DEBUG_FS printl("bytes_start=%d bytes_end=%d (in fre_smap_bit)\n",bytes_start,bytes_end); #endif //读取smap数据 rw_sector(INFO_FS_READ, ROOT_DEVICE, sector_index*SECTOR_SIZE, sector_length*SECTOR_SIZE, TASK_FS, fsbuf); /*分为三步处理: bits: ------------------------------------------------- | | | | | | bits_index 8m ^ 8(m+1) 8n ^ 8(n+1) step: | 1| 2 | 3 | */ for(bits_index=bits_off;bits_index%BITS_PER_BYTE!=0 && bits_index<bits_off+bits_length;bits_index++){ #ifdef DEBUG_FS printl("bits_index=%d(step 1. in fre_smap_bit)",bits_index); #endif fsbuf[bits_index/BITS_PER_BYTE] &=~(1<<bits_index%BITS_PER_BYTE); } #ifdef DEBUG_FS printl("\n"); #endif for(bytes_index=bytes_start;bytes_index<bytes_end;bytes_index++){ #ifdef DEBUG_FS printl("bytes_index=%d(step 2. in fre_smap_bit)",bytes_index); #endif fsbuf[bytes_index]=0; } #ifdef DEBUG_FS printl("\n"); #endif if(bytes_start<bytes_end){/*需要step3操作的情况*/ for(bits_index=bytes_end*BITS_PER_BYTE;bits_index<bits_off+bits_length;bits_index++){ #ifdef DEBUG_FS printl("bits_index=%d(step 3. in fre_smap_bit)",bits_index); #endif fsbuf[bits_index/BITS_PER_BYTE] &=~(1<<bits_index%BITS_PER_BYTE); } } /* #ifdef DEBUG_FS */ printl("\n"); /* #endif */ //更新smap数据 rw_sector(INFO_FS_WRITE, ROOT_DEVICE, sector_index*SECTOR_SIZE, sector_length*SECTOR_SIZE, TASK_FS, fsbuf); }
/* Get some informations on the FLASH upgrade: - size - ROM base address - os version - calc type */ int ti68k_get_tib_infos(const char *filename, IMG_INFO *tib, int preload) { FlashContent content; FlashContent *ptr; int nheaders = 0; int i; // No filename, exits if(!strcmp(g_basename(filename), "")) return ERR_CANT_OPEN; // Check valid file if(!tifiles_file_is_ti(filename)) return ERR_NOT_TI_FILE; if(!tifiles_file_is_tib(filename)) return ERR_INVALID_UPGRADE; // Load file if(tifiles_file_read_flash(filename, &content) != 0) return ERR_INVALID_UPGRADE; // count headers for (ptr = &content; ptr != NULL; ptr = ptr->next) nheaders++; // keep the last one (data) for (i = 0, ptr = &content; i < nheaders - 1; i++) ptr = ptr->next; // Load TIB into memory and relocate at SPP if(tib->data == NULL) tib->data = malloc(SPP + ptr->data_length + 4); if(tib->data == NULL) return ERR_MALLOC; memset(tib->data + SPP, 0xff, ptr->data_length); memcpy(tib->data + SPP, ptr->data_part, ptr->data_length); // Update current rom infos tib->rom_base = tib->data[BO+5 + SPP] & 0xf0; // libtifiles can't distinguish TI89/TI89t and 92+/V200. We need to look. switch(ptr->device_type & 0xff) { case DEVICE_TYPE_89: // can be a Titanium, too switch(tib->rom_base & 0xff) { case 0x20: tib->calc_type = TI89; break; case 0x80: tib->calc_type = TI89t; break; default: return ERR_INVALID_UPGRADE; } break; case DEVICE_TYPE_92P: switch(tib->rom_base & 0xff) { case 0x20: tib->calc_type = V200; break; case 0x40: tib->calc_type = TI92p; break; default: return ERR_INVALID_UPGRADE; } break; default: printl(0, "TIB problem: %02x!\n", 0xff & ptr->device_type); return ERR_INVALID_UPGRADE; break; } tib->flash = FLASH_ROM; tib->has_boot = 0; tib->size = ptr->data_length + SPP; get_rom_version(tib->data, tib->size, tib->version); tifiles_content_delete_flash(&content); if(!preload) free(tib->data); return 0; }
/* Convert a romdump into an image. This kind of image is complete (boot & certificate). */ int ti68k_convert_rom_to_image(const char *srcname, const char *dirname, char **dstname) { FILE *f; int err; IMG_INFO img; char *ext; gchar *basename; *dstname = NULL; // No filename, exits if(!strcmp(g_basename(srcname), "")) return ERR_CANT_OPEN; // Preload romdump memset(&img, 0, sizeof(IMG_INFO)); err = ti68k_get_rom_infos(srcname, &img, !0); if(err) { free(img.data); printl(0, _("Unable to get informations on ROM dump: %s\n"), srcname); return err; } ti68k_display_rom_infos(&img); // Create destination file basename = g_path_get_basename(srcname); ext = strrchr(basename, '.'); *ext='\0'; strcat(basename, ".img"); *dstname = g_strconcat(dirname, basename, NULL); g_free(basename); // Open dest file f = fopen(*dstname, "wb"); if(f == NULL) { fprintf(stderr, "Unable to open this file: <%s>\n", *dstname); return ERR_CANT_OPEN; } // Some V200 and TI89 Titanium ROMs are half the size if((img.size < 4*MB) && (img.calc_type == V200 || img.calc_type == TI89t)) { img.size = 4*MB; img.data = realloc(img.data, 4*MB + 4); printf("Completing image to 4MB !\n"); memset(img.data + 2*MB, 0xff, 2*MB); } // Fill header strcpy(img.signature, "TiEmu img v2.00"); img.header_size = sizeof(IMG_INFO); img.revision = IMG_REV; // Write file fwrite(&img, 1, sizeof(IMG_INFO), f); fwrite(img.data, sizeof(char), img.size, f); // Close file fclose(f); return 0; }
/* * Produces a number of object files in /tmp named objname.o.pid.o * with no external dependencies. * * gen_stub_prog is the address to the client stub generation prog * st_object is the address of the symmetric trust object. * * This is kind of a big hack. */ void gen_stubs_and_link(char *gen_stub_prog, struct service_symbs *services) { int pid = getpid(); char tmp_str[2048]; while (services) { int i; struct symb_type *symbs = &services->undef; char dest[256]; char tmp_name[256]; char *obj_name, *orig_name, *str; orig_name = services->obj; obj_name = basename(services->obj); sprintf(tmp_name, "/tmp/%s.%d", obj_name, pid); /* if (symbs->num_symbs == 0) { sprintf(tmp_str, "cp %s %s.o", orig_name, tmp_name); system(tmp_str); str = malloc(strlen(tmp_name)+3); strcpy(str, tmp_name); strcat(str, ".o"); free(services->obj); services->obj = str; services = services->next; continue; } */ /* make the command line for an invoke the stub generator */ strcpy(tmp_str, gen_stub_prog); if (symbs->num_symbs > 0) { strcat(tmp_str, " "); strcat(tmp_str, symbs->symbs[0].name); } for (i = 1 ; i < symbs->num_symbs ; i++) { strcat(tmp_str, ","); strcat(tmp_str, symbs->symbs[i].name); } /* invoke the stub generator */ sprintf(dest, " > %s_stub.S", tmp_name); strcat(tmp_str, dest); printl(PRINT_DEBUG, "%s\n", tmp_str); system(tmp_str); /* compile the stub */ sprintf(tmp_str, GCC_BIN " -m32 -c -o %s_stub.o %s_stub.S", tmp_name, tmp_name); system(tmp_str); /* link the stub to the service */ sprintf(tmp_str, LINKER_BIN " -m elf_i386 -r -o %s.o %s %s_stub.o", tmp_name, orig_name, tmp_name); system(tmp_str); /* Make service names reflect their new linked versions */ str = malloc(strlen(tmp_name)+3); strcpy(str, tmp_name); strcat(str, ".o"); free(services->obj); services->obj = str; sprintf(tmp_str, "rm %s_stub.o %s_stub.S", tmp_name, tmp_name); system(tmp_str); services = services->next; } return; }
/* Get some informations on the ROM dump: - size - ROM base address - FLASH/EPROM - os version - calc type Note: if the data field is NULL, memory is allocated. Otherwise, data is overwritten. Thanks to Kevin for HW2 detection code. */ int ti68k_get_rom_infos(const char *filename, IMG_INFO *rom, int preload) { FILE *file; HW_PARM_BLOCK hwblock; // No filename, exits if(!strcmp(g_basename(filename), "")) return ERR_CANT_OPEN; // Open file file = fopen(filename, "rb"); if(file == NULL) { printl(0, _("Unable to open this file: <%s>\n"), filename); return ERR_CANT_OPEN; } // Retrieve ROM size fseek(file, 0, SEEK_END); rom->size = ftell(file); fseek(file, 0, SEEK_SET); if(rom->size < 256) return ERR_INVALID_ROM_SIZE; if (rom->size > 4*MB) return ERR_INVALID_ROM_SIZE; if(rom->data == NULL) rom->data = malloc(rom->size + 4); if(rom->data == NULL) return ERR_MALLOC; memset(rom->data, 0xff, rom->size); fread(rom->data, 1, rom->size, file); fclose(file); rom->has_boot = 1; rom->rom_base = rom->data[0x05] & 0xf0; rom->flash = (rom->data[0x65] & 0x0f) ? 0 : FLASH_ROM; get_rom_version(rom->data, rom->size, rom->version); if(!rom->flash) { rom->calc_type = TI92; rom->hw_type = HW1; } else { // Get hw param block to determine calc type & hw type if(ti68k_get_hw_param_block(rom->data, rom->rom_base, &hwblock) == -1) return ERR_INVALID_ROM; ti68k_display_hw_param_block(&hwblock); switch(hwblock.hardwareID) { case HWID_TI92P: rom->calc_type = TI92p; break; case HWID_TI89: rom->calc_type = TI89; break; case HWID_V200: rom->calc_type = V200; break; case HWID_TI89T: rom->calc_type = TI89t; break; default: break; } if(rom->flash) { if(hwblock.len < 24) rom->hw_type = HW1; else rom->hw_type = (char)hwblock.gateArray; } } if(!preload) free(rom->data); return 0; }
/** * Perform the exec() system call. * * @return Zero if successful, otherwise -1. *****************************************************************************/ PUBLIC int do_exec() { /* get parameters from the message */ int name_len = mm_msg.NAME_LEN; /* length of filename */ int src = mm_msg.source; /* caller proc nr. */ assert(name_len < MAX_PATH); char pathname[MAX_PATH]; phys_copy((void*)va2la(TASK_MM, pathname), (void*)va2la(src, mm_msg.PATHNAME), name_len); pathname[name_len] = 0; /* terminate the string */ /* change the directory of task fs to the caller's work directory */ tell_fs(CHDIR, src, 0, 0); /* get the file size */ struct stat s; int ret = stat(pathname, &s); if (ret != 0) { printl("{MM} MM::do_exec()::stat() returns error. %s", pathname); return -1; } /* read the file */ int fd = open(pathname, O_RDWR); if (fd == -1) return -1; assert(s.st_size < MMBUF_SIZE); read(fd, mmbuf, s.st_size); close(fd); /* setup the arg stack */ int orig_stack_len = mm_msg.BUF_LEN; char stackcopy[PROC_ORIGIN_STACK]; phys_copy((void*)va2la(TASK_MM, stackcopy), (void*)va2la(src, mm_msg.BUF), orig_stack_len); /* clean up the image of the current process */ free_mem(src); /* the information about elf32 */ u32 start_text = 0, end_text = 0, start_data = 0, end_data = 0; /* overwrite the current proc image with the new one */ Elf32_Ehdr* elf_hdr = (Elf32_Ehdr*)(mmbuf); int i; for (i = 0; i < elf_hdr->e_phnum; i++) { Elf32_Phdr* prog_hdr = (Elf32_Phdr*)(mmbuf + elf_hdr->e_phoff + (i * elf_hdr->e_phentsize)); if (prog_hdr->p_type == PT_LOAD) { assert(prog_hdr->p_vaddr + prog_hdr->p_memsz < PROC_IMAGE_SIZE_DEFAULT); phys_copy((void*)va2la(src, (void*)prog_hdr->p_vaddr), (void*)va2la(TASK_MM, mmbuf + prog_hdr->p_offset), prog_hdr->p_filesz); if ((PF_R | PF_W) == prog_hdr->p_flags) { //the data segment // printl("elf32 .data start %d, size %d\n", prog_hdr->p_vaddr // , prog_hdr->p_memsz); start_data = prog_hdr->p_vaddr; end_data = start_data + prog_hdr->p_memsz; } else if ((PF_R | PF_X) == prog_hdr->p_flags) { //the text segment // printl("elf32 .text start %d, size %d\n", prog_hdr->p_vaddr // , prog_hdr->p_memsz); start_text = prog_hdr->p_vaddr; end_text = start_text + prog_hdr->p_memsz; } } } /* setup the arg stack */ // int orig_stack_len = mm_msg.BUF_LEN; // char stackcopy[PROC_ORIGIN_STACK]; // phys_copy((void*)va2la(TASK_MM, stackcopy), // (void*)va2la(src, mm_msg.BUF), // orig_stack_len); initial_brk(src, start_text, end_text, start_data, end_data); int * orig_stack = (int*)(VM_SIZE - PROC_ORIGIN_STACK); int delta = (int)orig_stack - (int)mm_msg.BUF; int argc = 0; if (orig_stack_len) { /* has args */ char **q = (char**)stackcopy; for (; *q != 0; q++,argc++) *q += delta; } phys_copy((void*)va2la(src, orig_stack), (void*)va2la(TASK_MM, stackcopy), orig_stack_len); proc_table[src].regs.ecx = argc; /* argc */ proc_table[src].regs.eax = (u32)orig_stack; /* argv */ /* setup eip & esp */ proc_table[src].regs.eip = elf_hdr->e_entry; /* @see _start.asm */ proc_table[src].regs.esp = VM_SIZE - PROC_ORIGIN_STACK; strcpy(proc_table[src].name, pathname); return 0; }
/** * Remove a file. * * @note We clear the i-node in inode_array[] although it is not really needed. * We don't clear the data bytes so the file is recoverable. * * @return On success, zero is returned. On error, -1 is returned. *****************************************************************************/ PUBLIC int do_unlink() { char pathname[MAX_PATH]; /* get parameters from the message */ int name_len = fs_msg.NAME_LEN; /* length of filename */ int src = fs_msg.source; /* caller proc nr. */ assert(name_len < MAX_PATH); phys_copy((void*)va2la(TASK_FS, pathname), (void*)va2la(src, fs_msg.PATHNAME), name_len); pathname[name_len] = 0; if (strcmp(pathname , "/") == 0) { printl("FS:do_unlink():: cannot unlink the root\n"); return -1; } int inode_nr = search_file(pathname); if (inode_nr == INVALID_INODE) { /* file not found */ printl("FS::do_unlink():: search_file() returns " "invalid inode: %s\n", pathname); return -1; } char filename[MAX_PATH]; struct inode * dir_inode; if (strip_path(filename, pathname, &dir_inode) != 0) return -1; struct inode * pin = get_inode(dir_inode->i_dev, inode_nr); if (pin->i_mode != I_REGULAR) { /* can only remove regular files */ printl("cannot remove file %s, because " "it is not a regular file.\n", pathname); return -1; } if (pin->i_cnt > 1) { /* the file was opened */ printl("cannot remove file %s, because pin->i_cnt is %d.\n", pathname, pin->i_cnt); return -1; } struct super_block * sb = get_super_block(pin->i_dev); /*************************/ /* free the bit in i-map */ /*************************/ int byte_idx = inode_nr / 8; int bit_idx = inode_nr % 8; assert(byte_idx < SECTOR_SIZE); /* we have only one i-map sector */ /* read sector 2 (skip bootsect and superblk): */ RD_SECT(pin->i_dev, 2); assert(fsbuf[byte_idx % SECTOR_SIZE] & (1 << bit_idx)); fsbuf[byte_idx % SECTOR_SIZE] &= ~(1 << bit_idx); WR_SECT(pin->i_dev, 2); /**************************/ /* free the bits in s-map */ /**************************/ /* * bit_idx: bit idx in the entire i-map * ... ____|____ * \ .-- byte_cnt: how many bytes between * \ | the first and last byte * +-+-+-+-+-+-+-+-+ V +-+-+-+-+-+-+-+-+ * ... | | | | | |*|*|*|...|*|*|*|*| | | | | * +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 * ...__/ * byte_idx: byte idx in the entire i-map */ bit_idx = pin->i_start_sect - sb->n_1st_sect + 1; byte_idx = bit_idx / 8; int bits_left = pin->i_nr_sects; int byte_cnt = (bits_left - (8 - (bit_idx % 8))) / 8; /* current sector nr. */ int s = 2 /* 2: bootsect + superblk */ + sb->nr_imap_sects + byte_idx / SECTOR_SIZE; RD_SECT(pin->i_dev, s); int i; /* clear the first byte */ for (i = bit_idx % 8; (i < 8) && bits_left; i++,bits_left--) { //assert((fsbuf[byte_idx % SECTOR_SIZE] >> i & 1) == 1); fsbuf[byte_idx % SECTOR_SIZE] &= ~(1 << i); } /* clear bytes from the second byte to the second to last */ int k; i = (byte_idx % SECTOR_SIZE) + 1; /* the second byte */ for (k = 0; k < byte_cnt; k++,i++,bits_left-=8) { if (i == SECTOR_SIZE) { i = 0; WR_SECT(pin->i_dev, s); RD_SECT(pin->i_dev, ++s); } //assert(fsbuf[i] == 0xFF); fsbuf[i] = 0; } /* clear the last byte */ if (i == SECTOR_SIZE) { i = 0; WR_SECT(pin->i_dev, s); RD_SECT(pin->i_dev, ++s); } unsigned char mask = ~((unsigned char)(~0) << bits_left); //assert((fsbuf[i] & mask) == mask); fsbuf[i] &= (~0) << bits_left; WR_SECT(pin->i_dev, s); /***************************/ /* clear the i-node itself */ /***************************/ pin->i_mode = 0; pin->i_size = 0; pin->i_start_sect = 0; pin->i_nr_sects = 0; sync_inode(pin); /* release slot in inode_table[] */ put_inode(pin); /************************************************/ /* set the inode-nr to 0 in the directory entry */ /************************************************/ int dir_blk0_nr = dir_inode->i_start_sect; int nr_dir_blks = (dir_inode->i_size + SECTOR_SIZE) / SECTOR_SIZE; int nr_dir_entries = dir_inode->i_size / DIR_ENTRY_SIZE; /* including unused slots * (the file has been * deleted but the slot * is still there) */ int m = 0; struct dir_entry * pde = 0; int flg = 0; int dir_size = 0; for (i = 0; i < nr_dir_blks; i++) { RD_SECT(dir_inode->i_dev, dir_blk0_nr + i); pde = (struct dir_entry *)fsbuf; int j; for (j = 0; j < SECTOR_SIZE / DIR_ENTRY_SIZE; j++,pde++) { if (++m > nr_dir_entries) break; if (pde->inode_nr == inode_nr) { /* pde->inode_nr = 0; */ memset(pde, 0, DIR_ENTRY_SIZE); WR_SECT(dir_inode->i_dev, dir_blk0_nr + i); flg = 1; break; } if (pde->inode_nr != INVALID_INODE) dir_size += DIR_ENTRY_SIZE; } if (m > nr_dir_entries || /* all entries have been iterated OR */ flg) /* file is found */ break; } assert(flg); if (m == nr_dir_entries) { /* the file is the last one in the dir */ dir_inode->i_size = dir_size; sync_inode(dir_inode); } return 0; }
PRIVATE void mkfs() { MESSAGE driver_msg; int bits_per_sect = SECTOR_SIZE * 8; struct part_info geo; driver_msg.type = DEV_IOCTL; driver_msg.DEVICE = MINOR(ROOT_DEV); driver_msg.REQUEST = DIOCTL_GET_GEO; driver_msg.BUF = &geo; driver_msg.PROC_NR = TASK_FS; assert(dd_map[MAJOR(ROOT_DEV)].driver_nr != INVALID_DRIVER); send_recv(BOTH, dd_map[MAJOR(ROOT_DEV)].driver_nr, &driver_msg); printl("dev base: 0x%x, dev size: 0x%x sectors\n", geo.base, geo.size); /***********************/ /* super block */ /***********************/ struct super_block sb; sb.magic = MAGIC_V1; sb.nr_inodes = bits_per_sect; sb.nr_sects = geo.size; sb.nr_imap_sects = 1; sb.nr_smap_sects = sb.nr_sects / bits_per_sect + 1; sb.nr_inode_sects = sb.nr_inodes * INODE_SIZE / SECTOR_SIZE; sb.n_1st_sect = 1 + 1 + sb.nr_imap_sects + sb.nr_smap_sects + sb.nr_inode_sects; sb.root_inode = ROOT_INODE; sb.inode_size = INODE_SIZE; sb.inode_isize_off = offsetof(struct inode, i_size); sb.inode_start_off = offsetof(struct inode, i_start_sect); sb.dir_ent_size = DIR_ENTRY_SIZE; sb.dir_ent_inode_off = offsetof(struct dir_entry, inode_nr); sb.dir_ent_fname_off = offsetof(struct dir_entry, name); memset(fsbuf, 0x90, SECTOR_SIZE); memcpy(fsbuf, &sb, SUPER_BLOCK_SIZE); WR_SECT(ROOT_DEV, 1); // write the super block printl( "devbase: 0x%x00, sb: 0x%x00, imap: 0x%x00, smap: 0x%x00\n" " inodes: 0x%x00, 1st_sector: 0x%x00\n", geo.base * 2, (geo.base + 1) * 2, (geo.base + 1 + 1) * 2, (geo.base + 1 + 1 + sb.nr_imap_sects) * 2, (geo.base + 1 + 1 + sb.nr_imap_sects + sb.nr_smap_sects) * 2, (geo.base + sb.n_1st_sect) * 2 ); /***********************/ /* inode Map */ /***********************/ memset(fsbuf, 0x0, SECTOR_SIZE); for (int i = 0; i < (NR_CONSOLES + 3); i++) fsbuf[0] |= 1 << i; assert(fsbuf[0] == 0x3F); /* 0011 1111 * || |||`- bit 0 : reserved * || ||`-- bit 1 : the frist inode which indicates '/' * || |`--- bit 2 : /dev_tty0 * || `---- bit 3 : /dev_tty1 * |`------ bit 4 : /dev_tty2 * `------- bit 5 : /cmd.tar */ WR_SECT(ROOT_DEV, 2); /***********************/ /* sector Map */ /***********************/ memset(fsbuf, 0x0, SECTOR_SIZE); int nr_sects = NR_DEFAULT_FILE_SECTS + 1; int i; for (i = 0; i < nr_sects / 8; i++) fsbuf[i] = 0xFF; for (int j = 0; j < nr_sects % 8; j++) fsbuf[i] |= (1 << i); WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects); memset(fsbuf, 0x0, SECTOR_SIZE); for (int i = 1; i < sb.nr_smap_sects; i++) WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + i); /* cmd.tar */ int bit_offset = INSTALL_START_SECT - sb.n_1st_sect + 1; // sect M <-> bit (M - sb.n_1stsect + 1) int bit_off_in_sect = bit_offset % (SECTOR_SIZE * 8); int bit_left = INSTALL_NR_SECTS; int cur_sect = bit_offset / (SECTOR_SIZE * 8); RD_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect); while (bit_left) { int byte_off = bit_off_in_sect / 8; /* this line is ineffecient in a loop, but I don't care */ fsbuf[byte_off] |= 1 << (bit_off_in_sect % 8); bit_left--; bit_off_in_sect++; if (bit_off_in_sect == (SECTOR_SIZE * 8)) { WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect); cur_sect++; RD_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect); bit_off_in_sect = 0; } } WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + cur_sect); /***********************/ /* inodes */ /***********************/ memset(fsbuf, 0x0, SECTOR_SIZE); struct inode *pi = (struct inode *)fsbuf; pi->i_mode = I_DIRECTORY; pi->i_size = DIR_ENTRY_SIZE * 5; // 5 files pi->i_start_sect = sb.n_1st_sect; pi->i_nr_sects = NR_DEFAULT_FILE_SECTS; for (int i = 0; i < NR_CONSOLES; i++) { pi = (struct inode *)(fsbuf + (INODE_SIZE * (i + 1))); pi->i_mode = I_CHAR_SPECIAL; pi->i_size = 0; pi->i_start_sect = MAKE_DEV(DEV_CHAR_TTY, i); pi->i_nr_sects = 0; } /* inode of `/cmd.tar' */ pi = (struct inode*)(fsbuf + (INODE_SIZE * (NR_CONSOLES + 1))); pi->i_mode = I_REGULAR; pi->i_size = INSTALL_NR_SECTS * SECTOR_SIZE; pi->i_start_sect = INSTALL_START_SECT; pi->i_nr_sects = INSTALL_NR_SECTS; WR_SECT(ROOT_DEV, 2 + sb.nr_imap_sects + sb.nr_smap_sects); /***********************/ /* '/' */ /***********************/ memset(fsbuf, 0x0, SECTOR_SIZE); struct dir_entry *pde = (struct dir_entry *)fsbuf; pde->inode_nr = 1; strcpy(pde->name, "."); for (int i = 0; i < NR_CONSOLES; i++) { pde++; pde->inode_nr = i + 2; sprintf(pde->name, "dev_tty%d", i); } (++pde)->inode_nr = NR_CONSOLES + 2; strcpy(pde->name, "cmd.tar"); WR_SECT(ROOT_DEV, sb.n_1st_sect); }
/** * Perform the exec() system call. * * @return Zero if successful, otherwise -1. *****************************************************************************/ PUBLIC int do_exec() { /* get parameters from the message */ int name_len = mm_msg.NAME_LEN; /* length of filename */ int src = mm_msg.source; /* caller proc nr. */ assert(name_len < MAX_PATH); char pathname[MAX_PATH]; phys_copy((void*)va2la(TASK_MM, pathname), (void*)va2la(src, mm_msg.PATHNAME), name_len); pathname[name_len] = 0; /* terminate the string */ /* get the file size */ struct stat s; int ret = stat(pathname, &s); if (ret != 0) { printl("{MM} MM::do_exec()::stat() returns error. %s", pathname); return -1; } /* read the file */ int fd = open(pathname, O_RDWR); if (fd == -1) return -1; assert(s.st_size < MMBUF_SIZE); read(fd, mmbuf, s.st_size); close(fd); /* overwrite the current proc image with the new one */ Elf32_Ehdr* elf_hdr = (Elf32_Ehdr*)(mmbuf); int i; for (i = 0; i < elf_hdr->e_phnum; i++) { Elf32_Phdr* prog_hdr = (Elf32_Phdr*)(mmbuf + elf_hdr->e_phoff + (i * elf_hdr->e_phentsize)); if (prog_hdr->p_type == PT_LOAD) { assert(prog_hdr->p_vaddr + prog_hdr->p_memsz < PROC_IMAGE_SIZE_DEFAULT); phys_copy((void*)va2la(src, (void*)prog_hdr->p_vaddr), (void*)va2la(TASK_MM, mmbuf + prog_hdr->p_offset), prog_hdr->p_filesz); } } /* setup the arg stack */ int orig_stack_len = mm_msg.BUF_LEN; char stackcopy[PROC_ORIGIN_STACK]; phys_copy((void*)va2la(TASK_MM, stackcopy), (void*)va2la(src, mm_msg.BUF), orig_stack_len); u8 * orig_stack = (u8*)(PROC_IMAGE_SIZE_DEFAULT - PROC_ORIGIN_STACK); int delta = (int)orig_stack - (int)mm_msg.BUF; int argc = 0; if (orig_stack_len) { /* has args */ char **q = (char**)stackcopy; for (; *q != 0; q++,argc++) *q += delta; } phys_copy((void*)va2la(src, orig_stack), (void*)va2la(TASK_MM, stackcopy), orig_stack_len); proc_table[src].regs.ecx = argc; /* argc */ proc_table[src].regs.eax = (u32)orig_stack; /* argv */ /* setup eip & esp */ proc_table[src].regs.eip = elf_hdr->e_entry; /* @see _start.asm */ proc_table[src].regs.esp = PROC_IMAGE_SIZE_DEFAULT - PROC_ORIGIN_STACK; strcpy(proc_table[src].name, pathname); return 0; }
/* Convert an upgrade into an image. The image has neither boot block nor certificate. */ int ti68k_convert_tib_to_image(const char *srcname, const char *dirname, char **dstname, int hw_type) { FILE *f; int err; IMG_INFO img; char *ext; gchar *basename; int i, j; int num_blocks, last_block; int real_size; HW_PARM_BLOCK hwpb; *dstname = NULL; // No filename, exits if(!strcmp(g_basename(srcname), "")) return ERR_CANT_OPEN; // Preload upgrade memset(&img, 0, sizeof(IMG_INFO)); err = ti68k_get_tib_infos(srcname, &img, !0); if(err) { free(img.data); printl(0, _("Unable to get informations on FLASH upgrade: %s\n"), srcname); return err; } ti68k_display_tib_infos(&img); // Create destination file basename = g_path_get_basename(srcname); ext = strrchr(basename, '.'); *ext='\0'; strcat(basename, ".img"); *dstname = g_strconcat(dirname, basename, NULL); g_free(basename); // Open dest file f = fopen(*dstname, "wb"); if(f == NULL) { fprintf(stderr, "Unable to open this file: <%s>\n", *dstname); return ERR_CANT_OPEN; } // Fill header strcpy(img.signature, "TiEmu img v2.00"); img.header_size = sizeof(IMG_INFO); img.revision = IMG_REV; real_size = img.size - SPP; img.size = ti68k_get_rom_size(img.calc_type); if(img.calc_type == TI89t) img.hw_type = HW3; //default else if(hw_type == -1) img.hw_type = HW2; //default else img.hw_type = hw_type; // Write header fwrite(&img, 1, sizeof(IMG_INFO), f); // Write boot block memcpy(img.data, &img.data[SPP + BO], 256); fwrite(img.data, 1, 256, f); // Write hardware param block // fill structure hwpb.len = 24; switch(img.calc_type) { case TI89: hwpb.hardwareID = HWID_TI89; hwpb.hardwareRevision = img.hw_type - 1; break; case TI92p: hwpb.hardwareID = HWID_TI92P; hwpb.hardwareRevision = img.hw_type - 1; break; case V200: hwpb.hardwareID = HWID_V200; hwpb.hardwareRevision = 2; break; case TI89t: hwpb.hardwareID = HWID_TI89T; hwpb.hardwareRevision = 2; break; } hwpb.bootMajor = hwpb.bootRevision = hwpb.bootBuild = 1; hwpb.gateArray = img.hw_type; ti68k_put_hw_param_block(img.data, img.rom_base, &hwpb); // write filler fputc(0xfe, f); fputc(0xed, f); fputc(0xba, f); fputc(0xbe, f); //fwrite(&hwpb, 1hwpb.len+2, f); // write address (pointer) fputc(0x00, f); fputc(img.rom_base, f); fputc(0x01, f); fputc(0x08, f); // write structure fputc(MSB(hwpb.len), f); fputc(LSB(hwpb.len), f); fputc(MSB(MSW(hwpb.hardwareID)), f); fputc(LSB(MSW(hwpb.hardwareID)), f); fputc(MSB(LSW(hwpb.hardwareID)), f); fputc(LSB(LSW(hwpb.hardwareID)), f); fputc(MSB(MSW(hwpb.hardwareRevision)), f); fputc(LSB(MSW(hwpb.hardwareRevision)), f); fputc(MSB(LSW(hwpb.hardwareRevision)), f); fputc(LSB(LSW(hwpb.hardwareRevision)), f); fputc(MSB(MSW(hwpb.bootMajor)), f); fputc(LSB(MSW(hwpb.bootMajor)), f); fputc(MSB(LSW(hwpb.bootMajor)), f); fputc(LSB(LSW(hwpb.bootMajor)), f); fputc(MSB(MSW(hwpb.hardwareRevision)), f); fputc(LSB(MSW(hwpb.hardwareRevision)), f); fputc(MSB(LSW(hwpb.hardwareRevision)), f); fputc(LSB(LSW(hwpb.hardwareRevision)), f); fputc(MSB(MSW(hwpb.bootBuild)), f); fputc(LSB(MSW(hwpb.bootBuild)), f); fputc(MSB(LSW(hwpb.bootBuild)), f); fputc(LSB(LSW(hwpb.bootBuild)), f); fputc(MSB(MSW(hwpb.gateArray)), f); fputc(LSB(MSW(hwpb.gateArray)), f); fputc(MSB(LSW(hwpb.gateArray)), f); fputc(LSB(LSW(hwpb.gateArray)), f); // Fill with 0xff up-to System Part for(i = 0x108 + hwpb.len+2; i < SPP; i++) fputc(0xff, f); // Copy FLASH upgrade at 0x12000 (SPP) num_blocks = real_size / 65536; for(i = 0; i < num_blocks; i++ ) { printl(0, "."); fflush(stdout); fwrite(&img.data[65536 * i + SPP], sizeof(char), 65536, f); } last_block = real_size % 65536; fwrite(&img.data[65536 * i + SPP], sizeof(char), last_block, f); printl(0, "\n"); printl(0, "Completing to %iMB size\n", img.size >> 20); for(j = SPP + real_size; j < img.size; j++) fputc(0xff, f); // Close file fclose(f); return 0; }
int exec(char *path, char **argv){ int i; char *s, *name; uint32_t sz, sp, off, argc, pa, ustack[3 + MAX_ARGC + 1]; pde_t *pgdir, *old_pgdir; struct inode *ip; struct elf32hdr eh; struct proghdr ph; printl("exec: try to read `%s` form disk...\n", path); pgdir = 0; i = off = 0; pgdir = (pde_t *)pmm_alloc(); kvm_init(pgdir); // exception handle pgdir // if ((ip = p2i(path)) == 0){ goto bad; } ilock(ip); // read elf header if (iread(ip, (char *)&eh, 0, sizeof(eh)) < (int)sizeof(eh)){ goto bad; } printl("exec: parsering elf\n"); // print_elfhdr(&eh); if (eh.magic != ELF_MAGIC){ goto bad; } printl("exec: load program section to memory\n"); // load program to memory sz = USER_BASE; for (i = 0, off = eh.phoff; i < eh.phnum; i++, off += sizeof(ph)){ if (iread(ip, (char *)&ph, off, sizeof(ph)) != sizeof(ph)){ goto bad; } // print_proghdr(&ph); if (ph.type != ELF_PROG_LOAD){ continue; } if (ph.memsz < ph.filesz){ goto bad; } if ((sz = uvm_alloc(pgdir, sz, ph.vaddr + ph.memsz)) == 0){ goto bad; } if (uvm_load(pgdir, ph.vaddr, ip, ph.off, ph.filesz) < 0){ goto bad; } } iunlockput(ip); ip = 0; printl("exec: build user stack\n"); /* build user stack */ sz = PAGE_ALIGN_UP(sz); if ((sz = uvm_alloc(pgdir, sz, sz + 2*PAGE_SIZE)) == 0){ goto bad; } /* leave a unaccessable page between kernel stack */ if (vmm_get_mapping(pgdir, sz - 2*PAGE_SIZE, &pa) == 0){ // sz is no mapped goto bad; } vmm_map(pgdir, sz - 2*PAGE_SIZE, pa, PTE_K | PTE_P | PTE_W); sp = sz; if (vmm_get_mapping(pgdir, sz - PAGE_SIZE, &pa) == 0){ // sz is no mapped goto bad; } pa += PAGE_SIZE; printl("exec: argv "); for (argc = 0; argv[argc]; argc++){ if (argc > MAX_ARGC) { goto bad; } printl("%d: %s ",argc, argv[argc]); // "+1" leava room for '\0' "&~3" align 4 sp = (sp - (strlen(argv[argc]) + 1)) & ~3; // sync with pa pa = (pa - (strlen(argv[argc]) + 1)) & ~3; strcpy((char *)pa, argv[argc]); ustack[3+argc] = sp; // argv[argc] } printl("\n"); ustack[3+argc] = 0; ustack[0] = 0xffffffff; ustack[1] = argc; // count of arguments ustack[2] = sp - (argc+1)*4; // pointer of argv[0] sp -= (3 + argc + 1)*4; pa -= (3 + argc + 1)*4; memcpy((void *)pa, ustack, (3 + argc + 1)*4); // combine for (name = s = path; *s; s++){ if (*s == '/'){ name = s + 1; } } printl("exec: prepare for new process `%s`\n", name); cli(); // 不清楚此处是否会有死锁或冲突的风险, 反正关中断也不要钱 strncpy(proc->name, name, sizeof(proc->name)); old_pgdir = proc->pgdir; proc->pgdir = pgdir; proc->size = sz - USER_BASE; proc->fm->eip = eh.entry; proc->fm->user_esp = sp; uvm_switch(proc); printl("exec: free old pgdir\n"); uvm_free(old_pgdir); old_pgdir = 0; old_pgdir ++; sti(); return 0; bad: printl("exec: bad\n"); if (pgdir){ uvm_free(pgdir); } if (ip){ iunlockput(ip); } return -1; }
/* Convert an romdump into image and replace SPP by upgrade. The resulting image has boot block. */ int ti68k_merge_rom_and_tib_to_image(const char *srcname1, const char *srcname2, const char *dirname, char **dstname) { FILE *f; int err; IMG_INFO img; char *ext; gchar *basename; int real_size; *dstname = NULL; // No filename, exits if(!strcmp(g_basename(srcname1), "")) return ERR_CANT_OPEN; if(!strcmp(g_basename(srcname2), "")) return ERR_CANT_OPEN; // Preload romdump memset(&img, 0, sizeof(IMG_INFO)); err = ti68k_get_rom_infos(srcname1, &img, !0); if(err) { free(img.data); printl(0, _("Unable to get informations on ROM dump: %s\n"), srcname1); return err; } ti68k_display_rom_infos(&img); // Save size real_size = img.size; // Load upgrade err = ti68k_get_tib_infos(srcname2, &img, !0); if(err) { free(img.data); printl(0, _("Unable to get informations on ROM dump: %s\n"), srcname2); return err; } ti68k_display_tib_infos(&img); // Create destination file basename = g_path_get_basename(srcname1); ext = strrchr(basename, '.'); *ext='\0'; strcat(basename, ".img"); *dstname = g_strconcat(dirname, basename, NULL); g_free(basename); // Restore size img.size = real_size; // Open dest file f = fopen(*dstname, "wb"); if(f == NULL) { fprintf(stderr, "Unable to open this file: <%s>\n", *dstname); return ERR_CANT_OPEN; } // Fill header strcpy(img.signature, "TiEmu img v2.00"); img.header_size = sizeof(IMG_INFO); img.revision = IMG_REV; img.has_boot = 1; // Write file fwrite(&img, 1, sizeof(IMG_INFO), f); fwrite(img.data, sizeof(char), img.size, f); // Close file fclose(f); return 0; }
static /* int */void do_write(MESSAGE *message){ u8 fsbuf[SECTOR_SIZE*DEFAULT_FILE_SECTOR_LENGTH]; const char *buf; int start_position,sector_length,length,data_sector_index; PROCESS *process; struct s_file_descriptor* pfd; process=pid2process(message->source_pid); if(message->fd==STDOUT && process->file_descriptor[message->fd]==NULL){ #ifdef DEBUG_FS printl("pid=%d (in do_write)\n",message->source_pid); #endif /*pfd->fd_inode->i_mode & I_CHAR_SPECIAL !=0*/ /* int device=pfd->fd_inode->i_start_sector_index; */ message->process_index=message->source_pid; send_receive(SEND,TASK_TTY/* dd_map[DRIVER(device)] */,message); /* message->type=INFO_SUSPEND_PROCESS; */ }else{ pfd=process->file_descriptor[message->fd]; if((pfd->fd_op_mode & O_WRONLY)==0 && (pfd->fd_op_mode & O_RDWR)==0){ set_error_index(FILE_CANNOT_WRITE); message->length=-1; return; } buf=message->arg_pointer; start_position=pfd->fd_position; if(start_position >= pfd->fd_inode->i_sectors_length*SECTOR_SIZE){ set_error_index(FILE_ALLOC_MEM_USEUP); message->length=-1; return; } length=min(start_position+message->length,pfd->fd_inode->i_sectors_length*SECTOR_SIZE); sector_length=(length+SECTOR_SIZE-1)/SECTOR_SIZE; data_sector_index=pfd->fd_inode->i_start_sector_index; #ifdef DEBUG_FS /* printl("1 %d %d length=%d\n",start_position,message->length,length); */ printl("sector_index=%d sector_length=%d(in do_write)\n",data_sector_index,sector_length); #endif rw_sector(INFO_FS_READ, ROOT_DEVICE, (data_sector_index)*SECTOR_SIZE, sector_length*SECTOR_SIZE, TASK_FS, fsbuf); memcpy(fsbuf+start_position,buf,length-start_position); /* printl("2 %d %d\n",data_sector_index,length); */ rw_sector(INFO_FS_WRITE, ROOT_DEVICE, (data_sector_index)*SECTOR_SIZE, sector_length*SECTOR_SIZE, TASK_FS, fsbuf); /* printl("3 inode.i_size=%d\n",pfd->fd_inode->i_size); */ pfd->fd_inode->i_size=length; /* printl("inode_index=%d\n",pfd->fd_inode->i_inode_index); */ sync_inode(pfd->fd_inode->i_inode_index,*(pfd->fd_inode)); pfd->fd_position=length; message->length=length-start_position; } }
/* Scan images in a given directory and write list into img_list.txt. */ int ti68k_scan_images(const char *dirname, const char *filename) { FILE *file; IMG_INFO img; GDir *dir; GError *error = NULL; G_CONST_RETURN gchar *dirent; gchar *path, *str; int ret; struct stat f_info; char *line[7]; printl(0, _("Scanning images/upgrades... ")); // Create file (and overwrite) file = fopen(filename, "wt"); if(file == NULL) { fprintf(stderr, _("Unable to open this file: <%s>\n"), filename); return ERR_CANT_OPEN; } // List all files available in the directory dir = g_dir_open(dirname, 0, &error); if (dir == NULL) { fprintf(stderr, _("Opendir error\n")); return ERR_CANT_OPEN_DIR; } while ((dirent = g_dir_read_name(dir)) != NULL) { if (dirent[0] == '.') continue; path = g_strconcat(dirname, dirent, NULL); ret = stat(path, &f_info); if(ret == -1) { fprintf(stderr, _("Can not stat: <%s>\n"), dirent); perror("stat: "); } else { if(ti68k_is_a_img_file(path)) { memset(&img, 0, sizeof(IMG_INFO)); ret = ti68k_get_img_infos(path, &img); if(ret) { fprintf(stderr, _("Can not get ROM/update info: <%s>\n"), path); break; } } else continue; str = g_strdup_printf("%iKB", (int)(img.size >> 10)); line[0] = (char *)dirent; line[1] = (char *)ti68k_calctype_to_string(img.calc_type); line[2] = img.version; line[3] = (char *)ti68k_romtype_to_string(img.flash); line[4] = str; line[5] = img.has_boot ? _("yes") : _("no"); line[6] = (char *)ti68k_hwtype_to_string(img.hw_type); fprintf(file, "%s,%s,%s,%s,%s,%s,%s\n", line[0], line[1], line[2], line[3], line[4], line[5], line[6]); g_free(str); } g_free(path); } // Close g_dir_close(dir); fclose(file); printl(0, _("Done.\n")); return 0; }
/***************************************************************************** * spin *****************************************************************************/ PUBLIC void spin(char * func_name) { printl(""); while (1) {} }
//**************************************************************************** static int print (char **out, int *varg) { int post_decimal ; int width, pad ; unsigned dec_width = 6 ; int pc = 0; char *format = (char *) (*varg++); char scr[2]; for (; *format != 0; ++format) { if (*format == '%') { ++format; width = pad = 0; if (*format == '\0') break; if (*format == '%') goto out; if (*format == '-') { ++format; pad = PAD_RIGHT; } while (*format == '0') { ++format; pad |= PAD_ZERO; } post_decimal = 0 ; if (*format == '.' || (*format >= '0' && *format <= '9')) { while (1) { if (*format == '.') { post_decimal = 1 ; dec_width = 0 ; format++ ; } else if ((*format >= '0' && *format <= '9')) { if (post_decimal) { dec_width *= 10; dec_width += *format - '0'; } else { width *= 10; width += *format - '0'; } format++ ; } else { break; } } } int ll = 0; if (*format == 'l') { ++format; if (*format == 'l') { ++format; ll = 1; } } switch (*format) { case 's': { char *s = *((char **) varg++); //lint !e740 // printf("[%s] w=%u\n", s, width) ; pc += prints (out, s ? s : "(null)", width, pad); } break; case 'd': if (ll) { if (((unsigned int)varg & 7) != 0) varg++; // MIPS requires 8 byte aligned long longs long long *llptr = (long long *) varg; long long llval = *llptr++; varg = (int *) llptr; pc += printl (out, llval, 10, 1, width, pad, 'a'); } else { pc += printi (out, *varg++, 10, 1, width, pad, 'a'); } break; case 'x': if (ll) { if (((unsigned int)varg & 7) != 0) varg++; // MIPS requires 8 byte aligned long longs long long *llptr = (long long *) varg; long long llval = *llptr++; varg = (int *) llptr; pc += printl (out, llval, 16, 0, width, pad, 'a'); } else { pc += printi (out, *varg++, 16, 0, width, pad, 'a'); } break; case 'p': pc += prints (out, "0x", 0, 0); pc += printi (out, *varg++, 16, 0, width ? width : 8, pad ? pad : PAD_ZERO , 'a'); break; case 'X': if (ll) { if (((unsigned int)varg & 7) != 0) varg++; // MIPS requires 8 byte aligned long longs long long *llptr = (long long *) varg; long long llval = *llptr++; varg = (int *) llptr; pc += printl (out, llval, 16, 0, width, pad, 'A'); } else { pc += printi (out, *varg++, 16, 0, width, pad, 'A'); } break; case 'u': if (ll) { if (((unsigned int)varg & 7) != 0) varg++; // MIPS requires 8 byte aligned long longs long long *llptr = (long long *) varg; long long llval = *llptr++; varg = (int *) llptr; pc += printl (out, llval, 10, 0, width, pad, 'a'); } else { pc += printi (out, *varg++, 10, 0, width, pad, 'a'); } break; case 'c': /* char are converted to int then pushed on the stack */ scr[0] = *varg++; scr[1] = '\0'; pc += prints (out, scr, width, pad); break; case 'f': { //if (((unsigned int)varg & 7) != 0) varg++; // MIPS requires 8 byte aligned doubles double *dblptr = (double *) varg ; //lint !e740 !e826 convert to double pointer double dbl = *dblptr++ ; // increment double pointer varg = (int *) dblptr ; //lint !e740 copy updated pointer back to base pointer char bfr[81] ; // unsigned slen = dbl2stri(bfr, dbl, dec_width) ; // stuff_talkf("[%s], width=%u, dec_width=%u\n", bfr, width, dec_width) ; pc += prints (out, bfr, width, pad); } break; default: printchar (out, '%'); printchar (out, *format); break; } } else { out: printchar (out, *format); ++pc; } } if (out) **out = '\0'; return pc; }
PUBLIC int do_open() { int fd = -1; char pathname[MAX_PATH]; int flags = fs_msg.FLAGS; int name_len = fs_msg.NAME_LEN; int src = fs_msg.source; assert(name_len < MAX_PATH); memcpy((void*)va2la(TASK_FS, pathname), (void*)va2la(src, fs_msg.PATHNAME), name_len); pathname[name_len] = 0; int i; for(i=0; i<NR_FILES; i++) { /* a empty filp item */ if (pcaller -> filp[i] == 0) break; } fd = i; /* printl("PATHNAME: %s, NAME_LEN: %d, FD: %d\n", pathname, name_len, fd); */ if (fd <0 || fd >= NR_FILES) panic("file[] is full. PID: %d", proc2pid(pcaller)); for(i=0; i<NR_FILE_DESC; i++) { /* a empty file descriptor */ if (f_desc_table[i].fd_inode == 0) break; } if (i >= NR_FILE_DESC) panic("f_desc_table[] is full. PID: %d", proc2pid(pcaller)); // FIXME: search_file is wrong int inode_nr = search_file(pathname); struct inode* pin = 0; if (flags & O_CREAT) { if (inode_nr) { /* file exists */ printl("file exists\n"); return -1; } else { pin = create_file(pathname, flags); /* dump_inode(pin); */ } } else { assert(flags & O_RDWR); char filename[MAX_PATH]; struct inode* dir_inode; if (strip_path(filename, pathname, &dir_inode) != 0) return -1; pin = get_inode(dir_inode -> i_dev, inode_nr); } if (pin) { pcaller -> filp[fd] = &f_desc_table[i]; f_desc_table[i].fd_inode = pin; f_desc_table[i].fd_mode = flags; f_desc_table[i].fd_pos = 0; f_desc_table[i].fd_cnt = 1; int imode = pin -> i_mode & I_TYPE_MASK; if (imode == I_CHAR_SPECIAL) { /* tty */ MESSAGE msg; msg.type = DEV_OPEN; int dev = pin -> i_start_sect; assert(MAJOR(dev) == 4); assert(dd_map[MAJOR(dev)].driver_nr != INVALID_DRIVER); msg.DEVICE = MINOR(dev); send_recv(BOTH, dd_map[MAJOR(dev)].driver_nr, &msg); } else if (imode == I_DIRECTORY) { assert(pin -> i_num == ROOT_INODE); } else { assert(pin -> i_mode == I_REGULAR); } } else { return -1; } return fd; }
/*======================================================================* TestA *======================================================================*/ void TestA() { int fd; int i, n; char filename[MAX_FILENAME_LEN+1] = "blah"; const char bufw[] = "abcde"; const int rd_bytes = 3; char bufr[rd_bytes]; assert(rd_bytes <= strlen(bufw)); /* create */ fd = open(filename, O_CREAT | O_RDWR); assert(fd != -1); printl("File created: %s (fd %d)\n", filename, fd); /* write */ n = write(fd, bufw, strlen(bufw)); assert(n == strlen(bufw)); /* close */ close(fd); /* open */ fd = open(filename, O_RDWR); assert(fd != -1); printl("File opened. fd: %d\n", fd); /* read */ n = read(fd, bufr, rd_bytes); assert(n == rd_bytes); bufr[n] = 0; printl("%d bytes read: %s\n", n, bufr); /* close */ close(fd); char * filenames[] = {"/foo", "/bar", "/baz"}; /* create files */ for (i = 0; i < sizeof(filenames) / sizeof(filenames[0]); i++) { fd = open(filenames[i], O_CREAT | O_RDWR); assert(fd != -1); printl("File created: %s (fd %d)\n", filenames[i], fd); close(fd); } char * rfilenames[] = {"/bar", "/foo", "/baz", "/dev_tty0"}; /* remove files */ for (i = 0; i < sizeof(rfilenames) / sizeof(rfilenames[0]); i++) { if (unlink(rfilenames[i]) == 0) printl("File removed: %s\n", rfilenames[i]); else printl("Failed to remove file: %s\n", rfilenames[i]); } TestD(); char tty_name[] = "/dev_tty0"; char rdbuf[128]; int fd_stdin = open(tty_name, O_RDWR); assert(fd_stdin == 0); int fd_stdout = open(tty_name, O_RDWR); assert(fd_stdout == 1); // char filename[MAX_FILENAME_LEN+1] = "zsp01"; const char bufwns[80] = {0}; // const int rd_bytes = 3; // char bufr[rd_bytes]; clear(); welcome(); while (1) { printl("hunix->"); int r = read(fd_stdin, rdbuf, 70); rdbuf[r] = 0; //show(); if (strcmp(rdbuf, "process") == 0) { ProcessManage(); } else if(strcmp(rdbuf, "TextBook") == 0) { TextBook(fd_stdin, fd_stdout); } else if (strcmp(rdbuf, "filemng") == 0) { printf("File Manager is already running on CONSOLE-1 ! \n"); continue; }else if (strcmp(rdbuf, "help") == 0) { help(); } else if (strcmp(rdbuf, "NewFile") == 0) { NewFile(fd_stdin, fd_stdout); } else if(strcmp(rdbuf, "RemoveFile") == 0) { RemoveFile(fd_stdin, fd_stdout); } else if(strcmp(rdbuf, "WriteFile") == 0) { WriteFile(fd_stdin, fd_stdout); } else if(strcmp(rdbuf, "ReadFile") == 0) { ReadFile(fd_stdin, fd_stdout); } else if(strcmp(rdbuf, "Chess") == 0) { chess(fd_stdin, fd_stdout); } else if(strcmp(rdbuf, "Add") == 0) { Add(fd_stdin, fd_stdout); } else if(strcmp(rdbuf, "welcome") == 0) { welcome(); } else if(strcmp(rdbuf, "number") == 0) { number(fd_stdin, fd_stdout); } else if (strcmp(rdbuf, "clear") == 0) { clear(); } else printf("Command not found, please check!\n"); } spin("TestA"); }
/** * <Ring 1> The main loop of TASK FS. * *****************************************************************************/ PUBLIC void task_fs() { printl("Task FS begins.\n"); init_fs(); spin("FS"); }
void TestD() { printl("hello Ninux"); }
static void trans_vm_close(struct vm_area_struct *vma) { printl("trans_munmap\n"); return; }
program() { //check command syntax //edit filename if (dcount(COMMAND,FM)<2) abort("Syntax is 'edic osfilename'"); var verbose=OPTIONS.ucase().index("V"); var editor=osgetenv("VISUAL"); var linenopattern="$LINENO "; if (not editor) editor.osgetenv("EDITOR"); //TODO simplify this editor finding code //enable edit at first error for crimson editor (no quotes around filename for cedt) if (editor.lcase().index("cedt") and not editor.index("$") ) editor^=" /L:$LINENO $FILENAME"; //look for installed nano //if (SLASH eq "\\" and not index(PLATFORM_,"x64")) { var nanopath=""; if (SLASH eq "\\") { //look for nano.exe next to edic.exe if (not editor) nanopath=EXECPATH.swap("edic","nano"); if (nanopath.osfile()) editor="nano $LINENO'$FILENAME'"; } //look for nano in parent bin if (not editor) { nanopath="..\\bin\\nano.exe"; if (nanopath.osfile()) editor="nano $LINENO'$FILENAME'"; } //look for nano in release directory during exodus development if (not editor) { nanopath="..\\..\\release\\cygwin\\bin\\nano.exe"; if (nanopath.osfile()) editor="..\\..\\release\\cygwin\\bin\\nano $LINENO'$FILENAME'"; else { nanopath="..\\"^nanopath; if (nanopath.osfile()) editor="..\\..\\..\\release\\cygwin\\bin\\nano $LINENO'$FILENAME'"; } } if (editor.index("nano")) linenopattern="+$LINENO "; //otherwise on windows try to locate CYGWIN nano or vi var cygwinpath=""; if (not editor and SLASH eq "\\") { //from environment variable cygwinpath=osgetenv("CYGWIN_BIN"); //else from current disk if (not cygwinpath) cygwinpath="\\cygwin\\bin\\"; //else from c: if (not osdir(cygwinpath)) cygwinpath="c:\\cygwin\\bin\\"; //else give up if (not osdir(cygwinpath)) cygwinpath=""; if (cygwinpath and cygwinpath[-1] ne SLASH) cygwinpath^=SLASH; //editor=cygwinpath^"bash --login -i -c \"/bin/"; editor=cygwinpath; if (osfile(cygwinpath^"nano.exe") or osfile("nano.exe")) { editor="nano $LINENO'$FILENAME'"; if (osfile(cygwinpath^"nano.exe")) editor.splicer(1,0,cygwinpath); //editor^="\""; linenopattern="+$LINENO "; } else if (osfile(cygwinpath^"vi.exe") or osfile("vi.exe")) { editor="vi -c \":$LINENO\" $FILENAME"; if (osfile(cygwinpath^"vi.exe")) editor.splicer(1,0,cygwinpath); //editor^="\""; } else editor=""; } if (SLASH eq "\\") { //configure nanorc (on windows) //TODO same for non-windows //nano on windows looks for nanorc config file as follows (probably merges all found) //C:\cygwin\usr\local\etc\nanorc //C:\cygwin\etc\nanorc (only if cygwin exists) //C:\Documents and Settings\USERNAME\.nanorc ($HOMEDRIVE$HOMEPATH) var nanorcfilename; if (cygwinpath) { nanorcfilename=cygwinpath.field(SLASH,1,dcount(cygwinpath,SLASH)-2) ^ SLASH ^ "etc" ^ SLASH ^ "nanorc"; } else { nanorcfilename=osgetenv("HOME"); if (not nanorcfilename) nanorcfilename=osgetenv("HOMEDRIVE") ^ osgetenv("HOMEPATH"); if (nanorcfilename[-1] ne SLASH) nanorcfilename^=SLASH; nanorcfilename^=".nanorc"; } if (not osfile(nanorcfilename)) { //var nanorctemplatefilename=EXECPATH.field(SLASH,1,dcount(EXECPATH,SLASH)-1) ^ SLASH ^ "nanorc"; var nanorctemplatefilename=nanopath.field(SLASH,1,dcount(nanopath,SLASH)-1) ^ SLASH ^ "nanorc"; if (not osfile(nanorctemplatefilename)) nanorctemplatefilename.swapper("release","..\\release"); //if (not osfile(nanorctemplatefilename)) // nanorctemplatefilename.swapper("release","..\\"^PLATFORM_^"\\release"); if (oscopy(nanorctemplatefilename,nanorcfilename)) { printl("Copied " ^ nanorctemplatefilename.quote() ^ " to " ^ nanorcfilename.quote()); var ().input("Note: nano c++ syntax highlighting has been installed. Press Enter ... "); } else { errputl("Could not copy " ^ nanorctemplatefilename.quote() ^ " to " ^ nanorcfilename.quote()); if (not osfile(nanorctemplatefilename)) errputl("nano syntax highlighting file is missing."); } } if(not osgetenv("HOME")) ossetenv("HOME",osgetenv("HOMEDRIVE") ^ osgetenv("HOMEPATH")); } if (not editor) { if (SLASH eq "/") editor="nano "; else editor="notepad"; printl("Environment EDITOR not set. Using " ^ editor); } //editor="vi"; editor.swapper("nano ", "nano --const --nowrap --autoindent --suspend "); if (editor.index("nano")) printl("http://www.nano-editor.org/dist/v2.1/nano.html"); //configure nano syntax highlighting var filenames=field(COMMAND,FM,2,99999); var nfiles=dcount(filenames,FM); var filen=0; while (filen<nfiles) { filen+=1; var filename=filenames.a(filen).unquote(); //split out trailing line number after : var startatlineno=field(filename,":",2); if (startatlineno.isnum()) filename=field(filename,":",1); else startatlineno=""; filename.trimmerb("."); if (not index(field2(filename,SLASH,-1),".")) filename^=".cpp"; var iscompilable=filename.field2(".",-1)[1].lcase() ne "h"; //make absolute in case EDITOR changes current working directory var editcmd=editor; if (editcmd.index("$ABSOLUTEFILENAME")) { editcmd.swapper("$ABSOLUTEFILENAME","$FILENAME"); filename=oscwd()^SLASH^filename; } //prepare a skeleton exodus cpp file var newfile=false; if (iscompilable and not osfile(filename)) { var basefilename=field2(filename,SLASH,-1); basefilename=basefilename.field(".",dcount(basefilename,".")-1); var progtype; var question="1=Normal Program, 2=External Subroutine or Function"; //question^="\n3=main(), 4=simple so/dll\n"; question^="\n"^basefilename.quote()^" does not exist. Create what? (1-2) "; while (true) { if (basefilename.substr(1,5).lcase() eq "dict_") progtype=5; else progtype.input(question); if (progtype eq 2) progtype="classlib"; else if (progtype eq 3) progtype="main"; else if (progtype eq 4) progtype="mainlib"; else if (progtype eq 1) progtype="class"; else if (progtype eq 5) progtype="dict"; else stop(); break; } newfile=true; var blankfile=""; if (progtype eq "main" or progtype eq "mainlib") { startatlineno="4,9"; blankfile^="#include <exodus/exodus.h>\n"; blankfile^="\n"; blankfile^="program() {\n"; blankfile^="\tprintl(\""^basefilename^" says 'Hello World!'\");\n"; if (progtype eq "mainlib") blankfile^="\treturn 0;\n"; blankfile^="}\n"; if (progtype eq "mainlib") blankfile.swapper("program()","function "^basefilename^"()"); } else if (progtype eq "class" or progtype eq "classlib") { startatlineno="6,9"; blankfile^="#include <exodus/program.h>\n"; //programinit() as 2nd line to avoid ppl in external functions before programinit //blankfile^="\n"; blankfile^="programinit()\n"; blankfile^="\n"; blankfile^="function main("; //the .h maker not able to parse this yet and is rather clumsy anyway //if (progtype eq "classlib") // blankfile^="/*in arg1, out arg2*/"; blankfile^=") {\n"; blankfile^="\tprintl(\""^basefilename^" says 'Hello World!'\");\n"; blankfile^="\treturn 0;\n"; blankfile^="}\n"; blankfile^="\nprogramexit()"; blankfile^="\n"; if (progtype eq "classlib") blankfile.swapper("program","library"); } else if (progtype eq "dict") { startatlineno="6,9"; blankfile^="#include <exodus/dict.h>\n\n"; //programinit() as 2nd line to avoid ppl in external functions before programinit //blankfile^="\n"; blankfile^="dict(EXAMPLEDICTID1) {\n"; blankfile^="\tANS=RECORD(1)^\"x\";\n"; blankfile^="}\n\n"; blankfile^="dict(EXAMPLEDICTID2) {\n"; blankfile^="\tANS=RECORD(2)^\"x\";\n"; blankfile^="}\n"; } if (blankfile[1] ne "\n") blankfile^="\n"; if (SLASH ne "/") blankfile.swapper("\n","\r\n"); if (not oswrite(blankfile,filename)) stop("Cannot create "^filename^". Invalid file name, or no rights here."); // startatlineno="4,9"; //startatlineno=""; } var editcmd0=editcmd; var linenopattern0=linenopattern; //keep editing and compiling until no errors while (true) { editcmd=editcmd0; linenopattern=linenopattern0; //record the current file update timestamp var fileinfo=osfile(filename); //build the edit command if (editcmd.index("$LINENO")) { if (not startatlineno) linenopattern=""; else linenopattern.swapper("$LINENO",startatlineno.field(",",1)); editcmd.swapper("$LINENO",linenopattern); } if (editcmd.index("$FILENAME")) editcmd.swapper("$FILENAME",filename); else editcmd ^= " " ^ filename; //call the editor if (verbose) printl(editcmd); osshell(editcmd); //if the file hasnt been updated var fileinfo2=osfile(filename); if (fileinfo2 ne fileinfo) newfile=false; else { //delete the skeleton printl("File unchanged. Not saving."); if (newfile) osdelete(filename); //move to the next file break; } //clear the screen (should be cls on win) if (SLASH eq "/") osshell("clear"); //else // osshell("cls"); if (not iscompilable) break; //build the compiler command var compiler="compile"; var compileoptions=""; var compilecmd=compiler ^ " " ^ filename.quote() ^ compileoptions; //capture the output var compileoutputfilename=filename ^ ".2"; if (SLASH eq "/") compilecmd ^= " 2>&1 | tee " ^ compileoutputfilename.quote(); else compilecmd ^= " > " ^ compileoutputfilename.quote() ^ " 2>&1"; //call the compiler if (verbose) printl(compilecmd); osshell(compilecmd); //var tt; //tt.inputl("Press Enter ..."); //if any errors then loop back to edit again var errors; if (osread(errors,compileoutputfilename)) { osdelete(compileoutputfilename); if (SLASH ne "/") print(errors); startatlineno=""; var charn; //gnu style error lines if (charn=index(errors, ": error:")) { startatlineno=errors.substr(charn-9,9); //printl(startatlineno); startatlineno=startatlineno.field2(":",2); //printl(startatlineno); //msvc style error lines //test.cpp(6) : error C2143: syntax error : missing ';' before '}' } else if (charn=index(errors,") : error ")) { startatlineno=errors.substr(charn-10,10).field2("(",2); } if (startatlineno) { print("Press any key to re-edit at line "^startatlineno^" ... "); var().input(""); continue; } } break; } } }
/* * For a certain principal, collect any unreferenced and not_in * free list cbufs so that they can be reused. This is the * garbage-collection mechanism. * * Collect cbufs and add them onto the shared component's ring buffer. * * This function is semantically complicated. It can return no cbufs * even if they are available to force the pool of cbufs to be * expanded (the client will call cbuf_create in this case). * Or, the common case: it can return a number of available cbufs. */ int cbuf_collect(spdid_t spdid, unsigned long size) { struct cbuf_info *cbi; struct cbuf_comp_info *cci; struct cbuf_shared_page *csp; struct cbuf_bin *bin; int ret = 0; printl("cbuf_collect\n"); CBUF_TAKE(); cci = cbuf_comp_info_get(spdid); tracking_start(&cci->track, CBUF_COLLECT); if (unlikely(!cci)) ERR_THROW(-ENOMEM, done); if (size + cci->allocated_size <= cci->target_size) goto done; csp = cci->csp; if (unlikely(!csp)) ERR_THROW(-EINVAL, done); assert(csp->ring.size == CSP_BUFFER_SIZE); ret = CK_RING_SIZE(cbuf_ring, &csp->ring); if (ret != 0) goto done; /* * Go through all cbufs we own, and report all of them that * have no current references to them. Unfortunately, this is * O(N*M), N = min(num cbufs, PAGE_SIZE/sizeof(int)), and M = * num components. */ size = round_up_to_page(size); bin = cbuf_comp_info_bin_get(cci, size); if (!bin) ERR_THROW(0, done); cbi = bin->c; do { if (!cbi) break; /* * skip cbufs which are in freelist. Coordinates with cbuf_free to * detect such cbufs correctly. * We must check refcnt first and then next pointer. * * If do not check refcnt: the manager may check "next" before cbuf_free * (when it is NULL), then switch to client who calls cbuf_free to set * "next", decrease refcnt and add cbuf to freelist. Then switch back to * manager, but now it will collect this in-freelist cbuf. * * Furthermore we must check refcnt before the "next" pointer: * If not, similar to above case, the manager maybe preempted by client * between the manager checks "next" and refcnt. Therefore the manager * finds the "next" is null and refcnt is 0, and collect this cbuf. * Short-circuit can prevent reordering. */ assert(cbi->owner.m); if (!CBUF_REFCNT(cbi->owner.m) && !CBUF_IS_IN_FREELIST(cbi->owner.m) && !cbuf_referenced(cbi)) { struct cbuf_ring_element el = { .cbid = cbi->cbid }; cbuf_references_clear(cbi); if (!CK_RING_ENQUEUE_SPSC(cbuf_ring, &csp->ring, &el)) break; /* * Prevent other collection collecting those cbufs. * The manager checks if the shared ring buffer is empty upon * the entry, if not, it just returns. This is not enough to * prevent double-collection. The corner case is: * after the last one in ring buffer is dequeued and * before it is added to the free-list, the manager * appears. It may collect the last one again. */ cbi->owner.m->next = (struct cbuf_meta *)1; if (++ret == CSP_BUFFER_SIZE) break; } cbi = FIRST_LIST(cbi, next, prev); } while (cbi != bin->c); if (ret) cbuf_thd_wake_up(cci, ret*size); done: tracking_end(&cci->track, CBUF_COLLECT); CBUF_RELEASE(); return ret; } /* * Called by cbuf_deref. */ int cbuf_delete(spdid_t spdid, unsigned int cbid) { struct cbuf_comp_info *cci; struct cbuf_info *cbi; struct cbuf_meta *meta; int ret = -EINVAL, sz; printl("cbuf_delete\n"); CBUF_TAKE(); tracking_start(NULL, CBUF_DEL); cci = cbuf_comp_info_get(spdid); if (unlikely(!cci)) goto done; cbi = cmap_lookup(&cbufs, cbid); if (unlikely(!cbi)) goto done; meta = cbuf_meta_lookup(cci, cbid); /* * Other threads can access the meta data simultaneously. For * example, others call cbuf2buf which increase the refcnt. */ CBUF_REFCNT_ATOMIC_DEC(meta); /* Find the owner of this cbuf */ if (cbi->owner.spdid != spdid) { cci = cbuf_comp_info_get(cbi->owner.spdid); if (unlikely(!cci)) goto done; } if (cbuf_free_unmap(cci, cbi)) goto done; if (cci->allocated_size < cci->target_size) { cbuf_thd_wake_up(cci, cci->target_size - cci->allocated_size); } ret = 0; done: tracking_end(NULL, CBUF_DEL); CBUF_RELEASE(); return ret; } /* * Called by cbuf2buf to retrieve a given cbid. */ int cbuf_retrieve(spdid_t spdid, unsigned int cbid, unsigned long size) { struct cbuf_comp_info *cci, *own; struct cbuf_info *cbi; struct cbuf_meta *meta, *own_meta; struct cbuf_maps *map; vaddr_t dest; void *page; int ret = -EINVAL, off; printl("cbuf_retrieve\n"); CBUF_TAKE(); tracking_start(NULL, CBUF_RETRV); cci = cbuf_comp_info_get(spdid); if (!cci) {printd("no cci\n"); goto done; } cbi = cmap_lookup(&cbufs, cbid); if (!cbi) {printd("no cbi\n"); goto done; } /* shouldn't cbuf2buf your own buffer! */ if (cbi->owner.spdid == spdid) { printd("owner\n"); goto done; } meta = cbuf_meta_lookup(cci, cbid); if (!meta) {printd("no meta\n"); goto done; } assert(!(meta->nfo & ~CBUF_INCONSISENT)); map = malloc(sizeof(struct cbuf_maps)); if (!map) {printd("no map\n"); ERR_THROW(-ENOMEM, done); } if (size > cbi->size) {printd("too big\n"); goto done; } assert(round_to_page(cbi->size) == cbi->size); size = cbi->size; /* TODO: change to MAPPING_READ */ if (cbuf_alloc_map(spdid, &map->addr, NULL, cbi->mem, size, MAPPING_RW)) { printc("cbuf mgr map fail spd %d mem %p sz %lu cbid %u\n", spdid, cbi->mem, size, cbid); goto free; } INIT_LIST(map, next, prev); ADD_LIST(&cbi->owner, map, next, prev); CBUF_PTR_SET(meta, map->addr); map->spdid = spdid; map->m = meta; meta->sz = cbi->size >> PAGE_ORDER; meta->cbid_tag.cbid = cbid; own = cbuf_comp_info_get(cbi->owner.spdid); if (unlikely(!own)) goto done; /* * We need to inherit the relinquish bit from the sender. * Otherwise, this cbuf cannot be returned to the manager. */ own_meta = cbuf_meta_lookup(own, cbid); if (CBUF_RELINQ(own_meta)) CBUF_FLAG_ADD(meta, CBUF_RELINQ); ret = 0; done: tracking_end(NULL, CBUF_RETRV); CBUF_RELEASE(); return ret; free: free(map); goto done; } vaddr_t cbuf_register(spdid_t spdid, unsigned int cbid) { struct cbuf_comp_info *cci; struct cbuf_meta_range *cmr; void *p; vaddr_t dest, ret = 0; printl("cbuf_register\n"); CBUF_TAKE(); tracking_start(NULL, CBUF_REG); cci = cbuf_comp_info_get(spdid); if (unlikely(!cci)) goto done; cmr = cbuf_meta_lookup_cmr(cci, cbid); if (cmr) ERR_THROW(cmr->dest, done); /* Create the mapping into the client */ if (cbuf_alloc_map(spdid, &dest, &p, NULL, PAGE_SIZE, MAPPING_RW)) goto done; assert((unsigned int)p == round_to_page(p)); cmr = cbuf_meta_add(cci, cbid, p, dest); assert(cmr); ret = cmr->dest; done: tracking_end(NULL, CBUF_REG); CBUF_RELEASE(); return ret; } static void cbuf_shrink(struct cbuf_comp_info *cci, int diff) { int i, sz; struct cbuf_bin *bin; struct cbuf_info *cbi, *next, *head; for (i = cci->nbin-1 ; i >= 0 ; i--) { bin = &cci->cbufs[i]; sz = (int)bin->size; if (!bin->c) continue; cbi = FIRST_LIST(bin->c, next, prev); while (cbi != bin->c) { next = FIRST_LIST(cbi, next, prev); if (!cbuf_free_unmap(cci, cbi)) { diff -= sz; if (diff <= 0) return; } cbi = next; } if (!cbuf_free_unmap(cci, cbi)) { diff -= sz; if (diff <= 0) return; } } if (diff > 0) cbuf_mark_relinquish_all(cci); }
/** * <Ring 1> The main loop of TASK FS. * *****************************************************************************/ PUBLIC void task_fs() { printl("Task FS begins.\n"); init_fs(); while (1) { send_recv(RECEIVE, ANY, &fs_msg); int msgtype = fs_msg.type; int src = fs_msg.source; pcaller = &proc_table[src]; switch (msgtype) { case OPEN: fs_msg.FD = do_open(); break; case CLOSE: fs_msg.RETVAL = do_close(); break; case READ: case WRITE: fs_msg.CNT = do_rdwt(); break; case UNLINK: fs_msg.RETVAL = do_unlink(); break; case RESUME_PROC: src = fs_msg.PROC_NR; break; case LS: fs_msg.RETVAL = do_ls(); break; /* case LSEEK: */ /* fs_msg.OFFSET = do_lseek(); */ /* break; */ /* case FORK: */ /* fs_msg.RETVAL = fs_fork(); */ /* break; */ /* case EXIT: */ /* fs_msg.RETVAL = fs_exit(); */ /* break; */ /* case STAT: */ /* fs_msg.RETVAL = do_stat(); */ /* break; */ default: dump_msg("FS::unknown message:", &fs_msg); assert(0); break; } #ifdef ENABLE_DISK_LOG char * msg_name[128]; msg_name[OPEN] = "OPEN"; msg_name[CLOSE] = "CLOSE"; msg_name[READ] = "READ"; msg_name[WRITE] = "WRITE"; msg_name[LSEEK] = "LSEEK"; msg_name[UNLINK] = "UNLINK"; msg_name[LS] = "LS"; /* msg_name[EXIT] = "EXIT"; */ /* msg_name[STAT] = "STAT"; */ switch (msgtype) { case LS: case CLOSE: case UNLINK: //dump_fd_graph("%s just finished.", msg_name[msgtype]); //panic(""); case OPEN: case READ: case WRITE: /* case FORK: */ /* case LSEEK: */ /* case EXIT: */ /* case STAT: */ break; case RESUME_PROC: case DISK_LOG: break; default: assert(0); } #endif /* reply */ if (fs_msg.type != SUSPEND_PROC) { fs_msg.type = SYSCALL_RET; send_recv(SEND, src, &fs_msg); } } }