static void writereg(uint8_t reg, uint8_t val) { ss(true); sendrecv(reg); sendrecv(val); ss(false); util_delay(100); }
static uint8_t readreg(uint8_t reg) { ss(true); sendrecv(reg | (1 << 7)); uint8_t val = sendrecv(0); ss(false); util_delay(100); return val; }
/* ack block, expect next */ int tftp_getnextblock(struct tftp_handle *h) { struct { u_char header[HEADER_SIZE]; struct tftphdr t; } wbuf; char *wtail; int res; struct tftphdr *t; bzero(&wbuf, sizeof(wbuf)); wbuf.t.th_opcode = htons((u_short) ACK); wbuf.t.th_block = htons((u_short) h->currblock); wtail = (char *) &wbuf.t.th_data; t = &h->lastdata.t; h->iodesc->xid = h->currblock + 1; /* expected block */ res = sendrecv(h->iodesc, sendudp, &wbuf.t, wtail - (char *) &wbuf.t, recvtftp, t, sizeof(*t) + RSPACE); if (res == -1) /* 0 is OK! */ return errno; h->currblock++; h->validsize = res; if (res < SEGSIZE) h->islastblock = 1; /* EOF */ return 0; }
/* 函数功能:MM的exit配套函数。用于销毁子进程的filp 输入参数:子进程pid cpid 输出参数:无 */ void fs_do_exit(int cpid) { TCB* p_tcb = cpid + task_table; int fd; for(fd = 0;fd < MAX_TASK_FILE;fd++) { if(p_tcb->filp[fd] == 0) continue; assert(p_tcb->filp[fd]->fd_inode->i_cnt > 0); if(--p_tcb->filp[fd]->fd_inode->i_cnt == 0) // inode共享者计数减一。如果没有其他进程使用该文件,则释放inode { if(p_tcb->filp[fd]->fd_inode->i_mode == I_MODE_CHAR) // 字符设备文件 { MSG msg; msg.type = TTY_MSG_UNION; msg.msg_union.tty_msg.para = DEV_CLOSE; msg.msg_union.tty_msg.sub_device = MINOR(p_tcb->filp[fd]->fd_inode->i_start_sect); disable_int(); if(tty_has_msg_tmp == 0) assert(sendrecv(BOTH,dd_map[MAJAR(p_tcb->filp[fd]->fd_inode->i_start_sect)],&msg) == 0); enable_int(); } } p_tcb->filp[fd]->fd_inode = 0; // 释放file_desc // p_tcb->filp[fd] = 0; // 释放filp } }
/* 函数功能:关闭文件 输入参数:进程指针 p_tcb 文件fd fd 输出参数:成功返回0,失败返回-1 */ int fs_close(int fd,TCB* p_tcb) { if(p_tcb->filp[fd]->fd_inode->i_cnt < 1) { printk("error! the file has not being open. fd: %d\n",fd); return -1; } if(p_tcb->filp[fd]->fd_inode->i_cnt == 1) // inode共享者计数为1,表示没有其他进程使用该文件 { if(p_tcb->filp[fd]->fd_inode->i_mode == I_MODE_CHAR) // 字符设备文件 { MSG msg; msg.type = TTY_MSG_UNION; msg.msg_union.tty_msg.para = DEV_CLOSE; msg.msg_union.tty_msg.sub_device = MINOR(p_tcb->filp[fd]->fd_inode->i_start_sect); disable_int(); if(tty_has_msg_tmp == 0) assert(sendrecv(BOTH,dd_map[MAJAR(p_tcb->filp[fd]->fd_inode->i_start_sect)],&msg) == 0); enable_int(); } else // 普通文件。关闭普通文件之前要先“同步文件缓冲” { sync_buff(p_tcb->filp[fd]->fd_inode,0); // 0:不释放缓冲 1:同步之后释放缓冲 } } p_tcb->filp[fd]->fd_inode->i_cnt--; // inode共享者计数减一。如果没有其他进程使用该文件,则计数变成0,表示释放inode p_tcb->filp[fd]->fd_inode = 0; // 释放file_desc p_tcb->filp[fd] = 0; // 释放filp return 0; }
// read data from the sensor. errlHndl_t SensorBase::readSensorData(uint8_t *& o_data) { // get sensor reading command only requires one byte of extra data, // which will be the sensor number, the command will return between // 3 and 5 bytes of data. size_t len = 1; // need to allocate some me to hold the sensor number this will be // deleted by the IPMI transport layer o_data = new uint8_t[len]; o_data[0] = getSensorNumber(); IPMI::completion_code cc = IPMI::CC_UNKBAD; // o_data will hold the response when this returns errlHndl_t l_err = sendrecv(IPMI::get_sensor_reading(), cc, len, (uint8_t *&)o_data); // if we didn't get an error back from the BT interface, but see a // bad completion code from the BMC, process the CC to see if we // need to create a PEL if( (l_err == NULL ) && (cc != IPMI::CC_OK) ) { l_err = processCompletionCode( cc ); } return l_err; };
/* ack block, expect next */ static int tftp_getnextblock(struct tftp_handle *h) { struct { u_char header[HEADER_SIZE]; struct tftphdr t; } __packed __aligned(4) wbuf; char *wtail; int res; struct tftphdr *t; /* * Ack previous block */ wbuf.t.th_opcode = htons((u_short) ACK); wtail = (char *) &wbuf.t.th_block; wbuf.t.th_block = htons((u_short) h->currblock); wtail += 2; t = &h->lastdata.t; h->iodesc->xid = h->currblock + 1; /* expected block */ res = sendrecv(h->iodesc, sendudp, &wbuf.t, wtail - (char *) &wbuf.t, recvtftp, t, sizeof(*t) + RSPACE); if (res == -1) /* 0 is OK! */ return (errno); h->currblock++; h->validsize = res; if (res < SEGSIZE) h->islastblock = 1; /* EOF */ return (0); }
/* Fetch required bootp information */ void bootp(int sock) { struct iodesc *d; struct bootp *bp; struct { u_char header[HEADER_SIZE]; struct bootp wbootp; } wbuf; struct { u_char header[HEADER_SIZE]; struct bootp rbootp; } rbuf; #ifdef BOOTP_DEBUG if (debug) printf("bootp: socket=%d\n", sock); #endif if (!bot) bot = getsecs(); if (!(d = socktodesc(sock))) { printf("bootp: bad socket. %d\n", sock); return; } #ifdef BOOTP_DEBUG if (debug) printf("bootp: d=%x\n", (u_int)d); #endif bp = &wbuf.wbootp; bzero(bp, sizeof(*bp)); bp->bp_op = BOOTREQUEST; bp->bp_htype = HTYPE_ETHERNET; /* 10Mb Ethernet (48 bits) */ bp->bp_hlen = 6; bp->bp_xid = htonl(d->xid); MACPY(d->myea, bp->bp_chaddr); bzero(bp->bp_file, sizeof(bp->bp_file)); bcopy(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)); d->myip = myip; d->myport = htons(IPPORT_BOOTPC); d->destip.s_addr = INADDR_BROADCAST; d->destport = htons(IPPORT_BOOTPS); (void)sendrecv(d, bootpsend, bp, sizeof(*bp), bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp)); /* Bump xid so next request will be unique. */ ++d->xid; }
int main(int argc, char * argv[]) { int x; MPI_Init(&argc, &argv); MPI_Comm_size(comm, &nprocs); MPI_Comm_rank(comm, &rank); left = (rank-1) % nprocs; right = (rank+1) % nprocs; x = sendrecv(); MPI_Finalize(); return 0; }
// // Synchronously send a set sensor reading command to the BMC, // the response is returned with the io_data pointer // errlHndl_t SensorBase::sendSetSensorReading( setSensorReadingRequest *& io_data, IPMI::completion_code& o_completion_code ) { size_t l_len = sizeof( setSensorReadingRequest ); o_completion_code = IPMI::CC_UNKBAD; // i_data will hold the response when this returns errlHndl_t l_err = sendrecv(IPMI::set_sensor_reading(), o_completion_code, l_len, (uint8_t *&)io_data); return l_err; }
/* send request, expect first block (or error) */ int tftp_makereq(struct tftp_handle *h) { struct { u_char header[HEADER_SIZE]; struct tftphdr t; u_char space[FNAME_SIZE + 6]; } wbuf; char *wtail; int l; ssize_t res; struct tftphdr *t; bzero(&wbuf, sizeof(wbuf)); wbuf.t.th_opcode = htons((u_short) RRQ); wtail = wbuf.t.th_stuff; l = strlen(h->path); bcopy(h->path, wtail, l + 1); wtail += l + 1; bcopy("octet", wtail, 6); wtail += 6; t = &h->lastdata.t; /* h->iodesc->myport = htons(--tftpport); */ h->iodesc->myport = htons(tftpport + (getsecs() & 0x3ff)); h->iodesc->destport = htons(IPPORT_TFTP); h->iodesc->xid = 1; /* expected block */ res = sendrecv(h->iodesc, sendudp, &wbuf.t, wtail - (char *) &wbuf.t, recvtftp, t, sizeof(*t) + RSPACE); if (res == -1) return errno; h->currblock = 1; h->validsize = res; h->islastblock = 0; if (res < SEGSIZE) h->islastblock = 1; /* very short file */ return 0; }
/* 函数功能:读文件 输入参数:进程指针 p_tcb 文件fd fd 读缓冲 buf 读大小 count 字节 输出参数:对于普通文件,输出实际读取字节数。 对于字符设备:0 请求成功,-1 请求失败(有其他进程正在请求输入) */ int fs_read(int fd,void * buf,int offset,int count,TCB* p_tcb) { File_Desc* p_fd; Inode* p_inode; buf = va2pa(p_tcb->pdb,buf); p_fd = p_tcb->filp[fd]; p_inode = p_fd->fd_inode; //---------------------------------------------------------- // 字符设备文件 if(p_inode->i_mode == I_MODE_CHAR) { MSG msg; msg.type = TTY_MSG_UNION; msg.msg_union.tty_msg.para = DEV_READ; msg.msg_union.tty_msg.sub_device = MINOR(p_inode->i_start_sect); msg.msg_union.tty_msg.req_caller = TASK_FS_PID; msg.msg_union.tty_msg.req_PID = p_tcb - task_table; msg.msg_union.tty_msg.req_buf = buf; msg.msg_union.tty_msg.req_count = count; disable_int(); if(tty_has_msg_tmp == 0) { if(sendrecv(SEND,dd_map[MAJAR(p_inode->i_start_sect)],&msg) == 0) { no_answer = 1; // 通知主循环将用户进程挂起 enable_int(); return 0; // 0 消息发送成功 } // 请求是否成功在这里还不能判断,需要在主循环中收到tty发来的消息才知道 } enable_int(); return -1; // -1 发送消息失败(可能构成死锁) } //---------------------------------------------------------- // 以下是普通文件 int cnt = file_buff_read( buf, p_fd->fd_inode, offset + p_fd->fd_pos, count); assert(cnt != -1); p_fd->fd_pos += offset + cnt; return cnt; }
/* * @brief Asynchronus message send * * @param[in] i_cmd, the command we're sending * @param[in] i_len, the length of the data * @param[in] i_data, the data we're sending * @param[in] i_type, the type of message we're sending * */ errlHndl_t send(const IPMI::command_t& i_cmd, size_t i_len, uint8_t* i_data, IPMI::message_type i_type) { IPMI::completion_code l_cc = IPMI::CC_UNKBAD; // We are calling a synchronous send in an asynchronous function // This is needed to enable asynchronous message sending before // runtime. A message should be synchronous during runtime, but // by ignoring the cc returned and clearing the data, we're making // a synchronous function "asynchronous". errlHndl_t l_err = sendrecv(i_cmd,l_cc,i_len,i_data); if(i_data != NULL) { delete i_data; } return l_err; }
/* 函数功能:写文件 输入参数:进程指针 p_tcb 文件fd fd 写缓冲 buf 写大小 count 字节 输出参数:成功返回实际写入字节数,失败返回-1 */ int fs_write(int fd,void * buf,int offset,int count,TCB* p_tcb) { File_Desc* p_fd; Inode* p_inode; buf = va2pa(p_tcb->pdb,buf); p_fd = p_tcb->filp[fd]; p_inode = p_fd->fd_inode; //---------------------------------------------------------- // 字符设备文件 if(p_inode->i_mode == I_MODE_CHAR) { MSG msg; msg.type = TTY_MSG_UNION; msg.msg_union.tty_msg.para = DEV_WRITE; msg.msg_union.tty_msg.sub_device = MINOR(p_inode->i_start_sect); msg.msg_union.tty_msg.req_buf = buf; msg.msg_union.tty_msg.req_count = count; disable_int(); if(tty_has_msg_tmp == 0) { if(sendrecv(BOTH,dd_map[MAJAR(p_inode->i_start_sect)],&msg) == -1) msg.msg_union.tty_msg.req_count = -1; enable_int(); return msg.msg_union.tty_msg.req_count; } enable_int(); return -1; } //---------------------------------------------------------- // 以下是普通文件 int cnt = file_buff_write( buf, p_fd->fd_inode, offset + p_fd->fd_pos, count); assert(cnt != -1); p_fd->fd_pos += offset + cnt; return cnt; }
/* * Make a rpc call; return length of answer * Note: Caller must leave room for headers. */ ssize_t rpc_call(struct iodesc *d, n_long prog, n_long vers, n_long proc, void *sdata, size_t slen, void **rdata, void **pkt) { ssize_t cc, rsize; struct auth_info *auth; struct rpc_call *call; struct rpc_reply *reply; char *send_head, *send_tail; void *ptr; n_long x; int port; /* host order */ #ifdef RPC_DEBUG if (debug) printf("rpc_call: prog=0x%x vers=%d proc=%d\n", prog, vers, proc); #endif port = rpc_getport(d, prog, vers); if (port == -1) return (-1); d->destport = htons(port); /* * Prepend authorization stuff and headers. * Note, must prepend things in reverse order. */ send_head = sdata; send_tail = (char *)sdata + slen; /* Auth verifier is always auth_null */ send_head -= sizeof(*auth); auth = (struct auth_info *)send_head; auth->authtype = htonl(RPCAUTH_NULL); auth->authlen = 0; /* Auth credentials: always auth unix (as root) */ send_head -= sizeof(struct auth_unix); bzero(send_head, sizeof(struct auth_unix)); send_head -= sizeof(*auth); auth = (struct auth_info *)send_head; auth->authtype = htonl(RPCAUTH_UNIX); auth->authlen = htonl(sizeof(struct auth_unix)); /* RPC call structure. */ send_head -= sizeof(*call); call = (struct rpc_call *)send_head; rpc_xid++; call->rp_xid = htonl(rpc_xid); call->rp_direction = htonl(RPC_CALL); call->rp_rpcvers = htonl(RPC_VER2); call->rp_prog = htonl(prog); call->rp_vers = htonl(vers); call->rp_proc = htonl(proc); ptr = NULL; cc = sendrecv(d, sendudp, send_head, send_tail - send_head, recvrpc, &ptr, (void **)&reply); #ifdef RPC_DEBUG if (debug) printf("callrpc: cc=%zd\n", cc); #endif if (cc == -1) return (-1); if (cc <= sizeof(*reply)) { errno = EBADRPC; free(ptr); return (-1); } /* * Check the RPC reply status. * The xid, dir, astatus were already checked. */ auth = &reply->rp_u.rpu_rok.rok_auth; x = ntohl(auth->authlen); if (x != 0) { #ifdef RPC_DEBUG if (debug) printf("callrpc: reply auth != NULL\n"); #endif errno = EBADRPC; free(ptr); return (-1); } x = ntohl(reply->rp_u.rpu_rok.rok_status); if (x != 0) { printf("callrpc: error = %ld\n", (long)x); errno = EBADRPC; free(ptr); return (-1); } rsize = cc - sizeof(*reply); *rdata = (void *)((uintptr_t)reply + sizeof(*reply)); *pkt = ptr; return (rsize); }
/* Fetch required bootp information */ void bootp(int sock) { struct iodesc *d; struct bootp *bp; struct { u_char header[UDP_TOTAL_HEADER_SIZE]; struct bootp wbootp; } wbuf; struct { u_char header[UDP_TOTAL_HEADER_SIZE]; struct bootp rbootp; } rbuf; unsigned int index; #ifdef BOOTP_DEBUG if (debug) printf("bootp: socket=%d\n", sock); #endif if (!bot) bot = getsecs(); if (!(d = socktodesc(sock))) { printf("bootp: bad socket. %d\n", sock); return; } #ifdef BOOTP_DEBUG if (debug) printf("bootp: d=%lx\n", (long)d); #endif bp = &wbuf.wbootp; (void)memset(bp, 0, sizeof(*bp)); bp->bp_op = BOOTREQUEST; bp->bp_htype = 1; /* 10Mb Ethernet (48 bits) */ bp->bp_hlen = 6; bp->bp_xid = htonl(d->xid); MACPY(d->myea, bp->bp_chaddr); (void)strncpy((char *)bp->bp_file, bootfile, sizeof(bp->bp_file)); (void)memcpy(bp->bp_vend, vm_rfc1048, sizeof(vm_rfc1048)); index = 4; #ifdef SUPPORT_DHCP bp->bp_vend[index++] = TAG_DHCP_MSGTYPE; bp->bp_vend[index++] = 1; bp->bp_vend[index++] = DHCPDISCOVER; #endif bootp_addvend(&bp->bp_vend[index]); d->myip.s_addr = INADDR_ANY; d->myport = htons(IPPORT_BOOTPC); d->destip.s_addr = INADDR_BROADCAST; d->destport = htons(IPPORT_BOOTPS); #ifdef SUPPORT_DHCP expected_dhcpmsgtype = DHCPOFFER; dhcp_ok = 0; #endif if (sendrecv(d, bootpsend, bp, sizeof(*bp), bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp)) == -1) { printf("bootp: no reply\n"); return; } #ifdef SUPPORT_DHCP if (dhcp_ok) { u_int32_t leasetime; index = 6; bp->bp_vend[index++] = DHCPREQUEST; bp->bp_vend[index++] = TAG_REQ_ADDR; bp->bp_vend[index++] = 4; (void)memcpy(&bp->bp_vend[9], &rbuf.rbootp.bp_yiaddr, 4); index += 4; bp->bp_vend[index++] = TAG_SERVERID; bp->bp_vend[index++] = 4; (void)memcpy(&bp->bp_vend[index], &dhcp_serverip.s_addr, 4); index += 4; bp->bp_vend[index++] = TAG_LEASETIME; bp->bp_vend[index++] = 4; leasetime = htonl(300); (void)memcpy(&bp->bp_vend[index], &leasetime, 4); index += 4; bootp_addvend(&bp->bp_vend[index]); expected_dhcpmsgtype = DHCPACK; if (sendrecv(d, bootpsend, bp, sizeof(*bp), bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp)) == -1) { printf("DHCPREQUEST failed\n"); return; } } #endif myip = d->myip = rbuf.rbootp.bp_yiaddr; servip = rbuf.rbootp.bp_siaddr; if (rootip.s_addr == INADDR_ANY) rootip = servip; (void)memcpy(bootfile, rbuf.rbootp.bp_file, sizeof(bootfile)); bootfile[sizeof(bootfile) - 1] = '\0'; if (IN_CLASSA(myip.s_addr)) nmask = IN_CLASSA_NET; else if (IN_CLASSB(myip.s_addr)) nmask = IN_CLASSB_NET; else nmask = IN_CLASSC_NET; #ifdef BOOTP_DEBUG if (debug) printf("'native netmask' is %s\n", intoa(nmask)); #endif /* Get subnet (or natural net) mask */ netmask = nmask; if (smask) netmask = smask; #ifdef BOOTP_DEBUG if (debug) printf("mask: %s\n", intoa(netmask)); #endif /* We need a gateway if root is on a different net */ if (!SAMENET(myip, rootip, netmask)) { #ifdef BOOTP_DEBUG if (debug) printf("need gateway for root ip\n"); #endif } /* Toss gateway if on a different net */ if (!SAMENET(myip, gateip, netmask)) { #ifdef BOOTP_DEBUG if (debug) printf("gateway ip (%s) bad\n", inet_ntoa(gateip)); #endif gateip.s_addr = 0; } #ifdef BOOTP_DEBUG if (debug) { printf("client addr: %s\n", inet_ntoa(myip)); if (smask) printf("subnet mask: %s\n", intoa(smask)); if (gateip.s_addr != 0) printf("net gateway: %s\n", inet_ntoa(gateip)); printf("server addr: %s\n", inet_ntoa(rootip)); if (rootpath[0] != '\0') printf("server path: %s\n", rootpath); if (bootfile[0] != '\0') printf("file name: %s\n", bootfile); } #endif /* Bump xid so next request will be unique. */ ++d->xid; }
/* Broadcast an ARP packet, asking who has addr on interface d */ uchar_t * arpwhohas(struct iodesc *d, struct in_addr addr) { int i; struct ether_arp *ah; struct arp_list *al; void *pkt; struct { struct ether_header eh; struct { struct ether_arp arp; uchar_t pad[18]; /* 60 - sizeof (...) */ } data; } wbuf; /* Try for cached answer first */ for (i = 0, al = arp_list; i < arp_num; ++i, ++al) if (addr.s_addr == al->addr.s_addr) return (al->ea); /* Don't overflow cache */ if (arp_num > ARP_NUM - 1) { arp_num = 1; /* recycle */ printf("arpwhohas: overflowed arp_list!\n"); } #ifdef ARP_DEBUG if (debug) printf("arpwhohas: send request for %s\n", inet_ntoa(addr)); #endif bzero((char *)&wbuf.data, sizeof (wbuf.data)); ah = &wbuf.data.arp; ah->arp_hrd = htons(ARPHRD_ETHER); ah->arp_pro = htons(ETHERTYPE_IP); ah->arp_hln = sizeof (ah->arp_sha); /* hardware address length */ ah->arp_pln = sizeof (ah->arp_spa); /* protocol address length */ ah->arp_op = htons(ARPOP_REQUEST); MACPY(d->myea, ah->arp_sha); bcopy(&d->myip, ah->arp_spa, sizeof (ah->arp_spa)); /* Leave zeros in arp_tha */ bcopy(&addr, ah->arp_tpa, sizeof (ah->arp_tpa)); /* Store ip address in cache (incomplete entry). */ al->addr = addr; pkt = NULL; ah = NULL; i = sendrecv(d, arpsend, &wbuf.data, sizeof (wbuf.data), arprecv, &pkt, (void **)&ah, NULL); if (i == -1) panic("arp: no response for %s", inet_ntoa(addr)); /* Store ethernet address in cache */ #ifdef ARP_DEBUG if (debug) { struct ether_header *eh; eh = (struct ether_header *)((uintptr_t)pkt + ETHER_ALIGN); printf("arp: response from %s\n", ether_sprintf(eh->ether_shost)); printf("arp: cacheing %s --> %s\n", inet_ntoa(addr), ether_sprintf(ah->arp_sha)); } #endif MACPY(ah->arp_sha, al->ea); ++arp_num; free(pkt); return (al->ea); }
/* * Make a rpc call; return length of answer * Note: Caller must leave room for headers. */ ssize_t rpc_call(struct iodesc *d, n_long prog, n_long vers, n_long proc, void *sdata, size_t slen, void *rdata, size_t rlen) { ssize_t cc; struct auth_info *auth; struct rpc_call *call; struct rpc_reply *reply; char *send_head, *send_tail; char *recv_head, *recv_tail; n_long x; int port; /* host order */ #ifdef RPC_DEBUG if (debug) printf("rpc_call: prog=0x%x vers=%d proc=%d\n", prog, vers, proc); #endif port = rpc_getport(d, prog, vers); if (port == -1) return (-1); d->destport = htons(port); /* * Prepend authorization stuff and headers. * Note, must prepend things in reverse order. */ send_head = sdata; send_tail = (char *)sdata + slen; /* Auth verifier is always auth_null */ send_head -= sizeof(*auth); auth = (struct auth_info *)send_head; auth->authtype = htonl(RPCAUTH_NULL); auth->authlen = 0; #if 1 /* Auth credentials: always auth unix (as root) */ send_head -= sizeof(struct auth_unix); bzero(send_head, sizeof(struct auth_unix)); send_head -= sizeof(*auth); auth = (struct auth_info *)send_head; auth->authtype = htonl(RPCAUTH_UNIX); auth->authlen = htonl(sizeof(struct auth_unix)); #else /* Auth credentials: always auth_null (XXX OK?) */ send_head -= sizeof(*auth); auth = send_head; auth->authtype = htonl(RPCAUTH_NULL); auth->authlen = 0; #endif /* RPC call structure. */ send_head -= sizeof(*call); call = (struct rpc_call *)send_head; rpc_xid++; call->rp_xid = htonl(rpc_xid); call->rp_direction = htonl(RPC_CALL); call->rp_rpcvers = htonl(RPC_VER2); call->rp_prog = htonl(prog); call->rp_vers = htonl(vers); call->rp_proc = htonl(proc); /* Make room for the rpc_reply header. */ recv_head = rdata; recv_tail = (char *)rdata + rlen; recv_head -= sizeof(*reply); cc = sendrecv(d, sendudp, send_head, send_tail - send_head, recvrpc, recv_head, recv_tail - recv_head); #ifdef RPC_DEBUG if (debug) printf("callrpc: cc=%d rlen=%d\n", cc, rlen); #endif if (cc < -1) return (-1); if ((size_t)cc <= sizeof(*reply)) { errno = EBADRPC; return (-1); } recv_tail = recv_head + cc; /* * Check the RPC reply status. * The xid, dir, astatus were already checked. */ reply = (struct rpc_reply *)recv_head; auth = &reply->rp_u.rpu_rok.rok_auth; x = ntohl(auth->authlen); if (x != 0) { #ifdef RPC_DEBUG if (debug) printf("callrpc: reply auth != NULL\n"); #endif errno = EBADRPC; return(-1); } x = ntohl(reply->rp_u.rpu_rok.rok_status); if (x != 0) { printf("callrpc: error = %d\n", x); errno = EBADRPC; return(-1); } recv_head += sizeof(*reply); return (ssize_t)(recv_tail - recv_head); }
/* Fetch required bootp infomation */ void bootp(int sock) { void *pkt; struct iodesc *d; struct bootp *bp; struct { uchar_t header[HEADER_SIZE]; struct bootp wbootp; } wbuf; struct bootp *rbootp; #ifdef BOOTP_DEBUG if (debug) printf("bootp: socket=%d\n", sock); #endif if (!bot) bot = getsecs(); if (!(d = socktodesc(sock))) { printf("bootp: bad socket. %d\n", sock); return; } #ifdef BOOTP_DEBUG if (debug) printf("bootp: d=%lx\n", (long)d); #endif bp = &wbuf.wbootp; bzero(bp, sizeof (*bp)); bp->bp_op = BOOTREQUEST; bp->bp_htype = 1; /* 10Mb Ethernet (48 bits) */ bp->bp_hlen = 6; bp->bp_xid = htonl(d->xid); MACPY(d->myea, bp->bp_chaddr); strncpy(bp->bp_file, bootfile, sizeof (bp->bp_file)); bcopy(vm_rfc1048, bp->bp_vend, sizeof (vm_rfc1048)); #ifdef SUPPORT_DHCP bp->bp_vend[4] = TAG_DHCP_MSGTYPE; bp->bp_vend[5] = 1; bp->bp_vend[6] = DHCPDISCOVER; bootp_fill_request(&bp->bp_vend[7]); #else bp->bp_vend[4] = TAG_END; #endif d->myip.s_addr = INADDR_ANY; d->myport = htons(IPPORT_BOOTPC); d->destip.s_addr = INADDR_BROADCAST; d->destport = htons(IPPORT_BOOTPS); #ifdef SUPPORT_DHCP expected_dhcpmsgtype = DHCPOFFER; dhcp_ok = 0; #endif if (sendrecv(d, bootpsend, bp, sizeof (*bp), bootprecv, &pkt, (void **)&rbootp, NULL) == -1) { printf("bootp: no reply\n"); return; } #ifdef SUPPORT_DHCP if (dhcp_ok) { uint32_t leasetime; bp->bp_vend[6] = DHCPREQUEST; bp->bp_vend[7] = TAG_REQ_ADDR; bp->bp_vend[8] = 4; bcopy(&rbootp->bp_yiaddr, &bp->bp_vend[9], 4); bp->bp_vend[13] = TAG_SERVERID; bp->bp_vend[14] = 4; bcopy(&dhcp_serverip.s_addr, &bp->bp_vend[15], 4); bp->bp_vend[19] = TAG_LEASETIME; bp->bp_vend[20] = 4; leasetime = htonl(300); bcopy(&leasetime, &bp->bp_vend[21], 4); bootp_fill_request(&bp->bp_vend[25]); expected_dhcpmsgtype = DHCPACK; free(pkt); if (sendrecv(d, bootpsend, bp, sizeof (*bp), bootprecv, &pkt, (void **)&rbootp, NULL) == -1) { printf("DHCPREQUEST failed\n"); return; } } #endif myip = d->myip = rbootp->bp_yiaddr; servip = rbootp->bp_siaddr; if (rootip.s_addr == INADDR_ANY) rootip = servip; bcopy(rbootp->bp_file, bootfile, sizeof (bootfile)); bootfile[sizeof (bootfile) - 1] = '\0'; if (!netmask) { if (IN_CLASSA(ntohl(myip.s_addr))) netmask = htonl(IN_CLASSA_NET); else if (IN_CLASSB(ntohl(myip.s_addr))) netmask = htonl(IN_CLASSB_NET); else netmask = htonl(IN_CLASSC_NET); #ifdef BOOTP_DEBUG if (debug) printf("'native netmask' is %s\n", intoa(netmask)); #endif } #ifdef BOOTP_DEBUG if (debug) printf("mask: %s\n", intoa(netmask)); #endif /* We need a gateway if root is on a different net */ if (!SAMENET(myip, rootip, netmask)) { #ifdef BOOTP_DEBUG if (debug) printf("need gateway for root ip\n"); #endif } /* Toss gateway if on a different net */ if (!SAMENET(myip, gateip, netmask)) { #ifdef BOOTP_DEBUG if (debug) printf("gateway ip (%s) bad\n", inet_ntoa(gateip)); #endif gateip.s_addr = 0; } /* Bump xid so next request will be unique. */ ++d->xid; free(pkt); }
/* * Ethernet (Reverse) Address Resolution Protocol (see RFC 903, and 826). */ int rarp_getipaddress(int sock) { struct iodesc *d; struct ether_arp *ap; struct { u_char header[ETHER_SIZE]; struct { struct ether_arp arp; u_char pad[18]; /* 60 - sizeof(arp) */ } data; } wbuf; struct { u_char header[ETHER_SIZE]; struct { struct ether_arp arp; u_char pad[24]; /* extra space */ } data; } rbuf; #ifdef RARP_DEBUG if (debug) printf("rarp: socket=%d\n", sock); #endif if (!(d = socktodesc(sock))) { printf("rarp: bad socket. %d\n", sock); return (-1); } #ifdef RARP_DEBUG if (debug) printf("rarp: d=%x\n", (u_int)d); #endif bzero((char*)&wbuf.data, sizeof(wbuf.data)); ap = &wbuf.data.arp; ap->arp_hrd = htons(ARPHRD_ETHER); ap->arp_pro = htons(ETHERTYPE_IP); ap->arp_hln = sizeof(ap->arp_sha); /* hardware address length */ ap->arp_pln = sizeof(ap->arp_spa); /* protocol address length */ ap->arp_op = htons(ARPOP_REVREQUEST); bcopy(d->myea, ap->arp_sha, 6); bcopy(d->myea, ap->arp_tha, 6); if (sendrecv(d, rarpsend, &wbuf.data, sizeof(wbuf.data), rarprecv, &rbuf.data, sizeof(rbuf.data)) < 0) { printf("No response for RARP request\n"); return (-1); } ap = &rbuf.data.arp; bcopy(ap->arp_tpa, (char *)&myip, sizeof(myip)); #if 0 /* XXX - Can NOT assume this is our root server! */ bcopy(ap->arp_spa, (char *)&rootip, sizeof(rootip)); #endif /* Compute our "natural" netmask. */ if (IN_CLASSA(myip.s_addr)) netmask = IN_CLASSA_NET; else if (IN_CLASSB(myip.s_addr)) netmask = IN_CLASSB_NET; else netmask = IN_CLASSC_NET; d->myip = myip; return (0); }
/* Fetch required bootp infomation */ void bootp(int sock, int flag) { struct iodesc *d; struct bootp *bp; struct { u_char header[HEADER_SIZE]; struct bootp wbootp; } wbuf; struct { u_char header[HEADER_SIZE]; struct bootp rbootp; } rbuf; #ifdef BOOTP_DEBUG if (debug) printf("bootp: socket=%d\n", sock); #endif if (!bot) bot = getsecs(); if (!(d = socktodesc(sock))) { printf("bootp: bad socket. %d\n", sock); return; } #ifdef BOOTP_DEBUG if (debug) printf("bootp: d=%lx\n", (long)d); #endif bp = &wbuf.wbootp; bzero(bp, sizeof(*bp)); bp->bp_op = BOOTREQUEST; bp->bp_htype = 1; /* 10Mb Ethernet (48 bits) */ bp->bp_hlen = 6; bp->bp_xid = htonl(d->xid); MACPY(d->myea, bp->bp_chaddr); strncpy(bp->bp_file, bootfile, sizeof(bp->bp_file)); bcopy(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)); #ifdef SUPPORT_DHCP bp->bp_vend[4] = TAG_DHCP_MSGTYPE; bp->bp_vend[5] = 1; bp->bp_vend[6] = DHCPDISCOVER; /* * If we are booting from PXE, we want to send the string * 'PXEClient' to the DHCP server so you have the option of * only responding to PXE aware dhcp requests. */ if (flag & BOOTP_PXE) { bp->bp_vend[7] = TAG_CLASSID; bp->bp_vend[8] = 9; bcopy("PXEClient", &bp->bp_vend[9], 9); bp->bp_vend[18] = TAG_PARAM_REQ; bp->bp_vend[19] = 7; bp->bp_vend[20] = TAG_ROOTPATH; bp->bp_vend[21] = TAG_HOSTNAME; bp->bp_vend[22] = TAG_SWAPSERVER; bp->bp_vend[23] = TAG_GATEWAY; bp->bp_vend[24] = TAG_SUBNET_MASK; bp->bp_vend[25] = TAG_INTF_MTU; bp->bp_vend[26] = TAG_SERVERID; bp->bp_vend[27] = TAG_END; } else bp->bp_vend[7] = TAG_END; #else bp->bp_vend[4] = TAG_END; #endif d->myip.s_addr = INADDR_ANY; d->myport = htons(IPPORT_BOOTPC); d->destip.s_addr = INADDR_BROADCAST; d->destport = htons(IPPORT_BOOTPS); #ifdef SUPPORT_DHCP expected_dhcpmsgtype = DHCPOFFER; dhcp_ok = 0; #endif if(sendrecv(d, bootpsend, bp, sizeof(*bp), bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp)) == -1) { printf("bootp: no reply\n"); return; } #ifdef SUPPORT_DHCP if(dhcp_ok) { u_int32_t leasetime; bp->bp_vend[6] = DHCPREQUEST; bp->bp_vend[7] = TAG_REQ_ADDR; bp->bp_vend[8] = 4; bcopy(&rbuf.rbootp.bp_yiaddr, &bp->bp_vend[9], 4); bp->bp_vend[13] = TAG_SERVERID; bp->bp_vend[14] = 4; bcopy(&dhcp_serverip.s_addr, &bp->bp_vend[15], 4); bp->bp_vend[19] = TAG_LEASETIME; bp->bp_vend[20] = 4; leasetime = htonl(300); bcopy(&leasetime, &bp->bp_vend[21], 4); if (flag & BOOTP_PXE) { bp->bp_vend[25] = TAG_CLASSID; bp->bp_vend[26] = 9; bcopy("PXEClient", &bp->bp_vend[27], 9); bp->bp_vend[36] = TAG_END; } else bp->bp_vend[25] = TAG_END; expected_dhcpmsgtype = DHCPACK; if(sendrecv(d, bootpsend, bp, sizeof(*bp), bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp)) == -1) { printf("DHCPREQUEST failed\n"); return; } } #endif myip = d->myip = rbuf.rbootp.bp_yiaddr; servip = rbuf.rbootp.bp_siaddr; if(rootip.s_addr == INADDR_ANY) rootip = servip; bcopy(rbuf.rbootp.bp_file, bootfile, sizeof(bootfile)); bootfile[sizeof(bootfile) - 1] = '\0'; if (!netmask) { if (IN_CLASSA(ntohl(myip.s_addr))) netmask = htonl(IN_CLASSA_NET); else if (IN_CLASSB(ntohl(myip.s_addr))) netmask = htonl(IN_CLASSB_NET); else netmask = htonl(IN_CLASSC_NET); #ifdef BOOTP_DEBUG if (debug) printf("'native netmask' is %s\n", intoa(netmask)); #endif } #ifdef BOOTP_DEBUG if (debug) printf("mask: %s\n", intoa(netmask)); #endif /* We need a gateway if root is on a different net */ if (!SAMENET(myip, rootip, netmask)) { #ifdef BOOTP_DEBUG if (debug) printf("need gateway for root ip\n"); #endif } /* Toss gateway if on a different net */ if (!SAMENET(myip, gateip, netmask)) { #ifdef BOOTP_DEBUG if (debug) printf("gateway ip (%s) bad\n", inet_ntoa(gateip)); #endif gateip.s_addr = 0; } /* Bump xid so next request will be unique. */ ++d->xid; }
/* 函数功能:打开文件 输入参数:文件名 pathname 打开方式 flags 进程指针 p_tcb 输出参数:成功返回进程filp中的fd下标,失败返回-1 */ int fs_open(char * pathname,int flags,TCB* p_tcb) { pathname = va2pa(p_tcb->pdb,pathname); DEV_Inode* p_devinode; int inode_nr; File_Desc* p_fd; Inode* p_inode; Dir_Entry* p_de; int i,j; // 读目录文件,寻找pathname,获得其inode_nr int file_offset = 0; for(i = 0,inode_nr = 0;i < ROOT_SECTS;i++,file_offset += SECTOR_SIZE) { file_buff_read(fsbuf,p_inode_de,file_offset,SECTOR_SIZE); for(j = 0,p_de = (Dir_Entry*)fsbuf;j < DIR_ENT_PER_SECT;j++,p_de++) { if(strcmp(p_de->name,pathname) == 0) { inode_nr = p_de->inode_nr; break; } } if(inode_nr != 0) break; } // 目录中寻找结束 if(inode_nr == 0) // 没找到dev_inode { if(flags == O_CREATE) { // 这里应该判断待创建打开的是否是普通文件 inode_nr = create_file(pathname); if(inode_nr == 0) { printk("create_file error! %s\n",pathname); return -1; // 创建文件失败 } } else { printk("no file : %s\n",pathname); return -1; // 没有找到,也没有创建文件 } } //printk("file : %s inode_nr : %d\n",pathname,inode_nr); // 找到了dev_inode编号inode_nr // 查看内存里的inode_table中是否存在该inode int i_dev = ROOT_DEV; Inode* p_inode_empty = 0; Inode* p_inode_empty1 = 0; for(p_inode = inode_table;p_inode < inode_table + MAX_ALL_INODE;p_inode++) { if(p_inode->i_cnt == 0) { if(p_inode_empty == 0) p_inode_empty = p_inode; // 第一个空位 if(p_inode_empty1 == 0 && p_inode->i_dev == 0 && p_inode->i_num == 0) p_inode_empty1 = p_inode; // 第一个从未被使用过的空位 } if(p_inode->i_dev != i_dev) continue; if(p_inode->i_num != inode_nr) continue; break; } int new_inode = 0; if(p_inode >= inode_table + MAX_ALL_INODE) // 不在inode_table里,需要手动添加 { // 在inode_table中寻找一个空位 if(p_inode_empty1 != 0) { p_inode = p_inode_empty1; } else { if(p_inode_empty == 0) { printk("inode_table full : %s----",pathname); return -1; // inode_table无空位 } p_inode = p_inode_empty; } new_inode = 1; // 用于判断该inode是否是新添加的 } // 此时p_inode的i_dev i_num正确,但是i_cnt可能是0。即:现在找到的inode可能是正在被其他进程共享的,也可能是被其他进程废弃的 // 在file_table中寻找一个空位 for(p_fd = file_table;p_fd < file_table + MAX_ALL_FILE;p_fd++) { if(p_fd->fd_inode == 0) break; } //printk(" p_fd : %d \n",p_fd - file_table); if(p_fd >= file_table + MAX_ALL_FILE) { printk("file_table full : %s----",pathname); return -1; // file_table无空位 } // 在进程filp数组中寻找一个空位 for(i = 0;i < MAX_TASK_FILE;i++) { if(p_tcb->filp[i] == 0) break; } if(i >= MAX_TASK_FILE) { printk("filp full : %s----",pathname); return -1; // filp无空位 } // 填充空位信息 p_tcb->filp[i] = p_fd; p_fd->fd_mode = RD_WR; p_fd->fd_pos = 0; p_fd->fd_inode = p_inode; p_inode->i_cnt++; if(new_inode == 1) // 新添加的inode,需要赋值 { //printk("new inode : %d\n",inode_nr); // 获取dev_inode指针 hd_read(ROOT_DEV,fsbuf,SECTOR_SIZE * (INODE_1ST_SECTS + inode_nr / INODE_PER_SECT),1); p_devinode = (DEV_Inode*)fsbuf; p_devinode += inode_nr % INODE_PER_SECT; // 赋值 p_inode->i_mode = p_devinode->i_mode; p_inode->i_size = p_devinode->i_size; p_inode->i_start_sect = p_devinode->i_start_sect; p_inode->i_nr_sects = p_devinode->i_nr_sects; p_inode->i_dev = ROOT_DEV; p_inode->i_num = inode_nr; } // 返回filp中的下标 //printk("file open : %s ----",pathname); if(p_inode->i_mode == I_MODE_CHAR) // 字符设备文件 { MSG msg; msg.type = TTY_MSG_UNION; msg.msg_union.tty_msg.para = DEV_OPEN; msg.msg_union.tty_msg.sub_device = MINOR(p_inode->i_start_sect); // 字符设备的i_start_sect即设备号 //printk("sub_device : %d ",msg.msg_union.tty_msg.sub_device); disable_int(); if(tty_has_msg_tmp == 0) { assert(sendrecv(BOTH,dd_map[MAJAR(p_inode->i_start_sect)],&msg) == 0); } enable_int(); } //printk(" i : %d----",i); return i; }