static int bd_realstrategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize) { prom_return_t ret; struct open_disk *od = (struct open_disk *)devdata; if (size % SRMDISK_SECSIZE) panic("bd_strategy: I/O not block multiple"); if (flag != F_READ) return(EROFS); if (rsize) *rsize = 0; ret.bits = prom_read(od->od_fd, size, buf, dblk + od->od_boff); if (ret.u.status) { D(printf("read error\n")); return (EIO); } if (rsize) *rsize = size; return (0); }
/* * Direct read if using block special, * otherwise use fs read */ int cpr_read(int fd, caddr_t buf, size_t len) { if (!statefile_special || volname) return (cpr_fs_read(fd, buf, len)); else return (prom_read(fd, buf, len, 0, 0)); }
int prom_mayget(void) { ssize_t rv; char c; rv = prom_read(prom_stdin_ihandle(), &c, 1, 0, BYTE); return (rv == 1 ? (int)c : -1); }
static int read_disk_block(struct boot_file_t *file, u64 block, int start, int length, void *buf) { u64 pos = block * 512; pos += partition_offset + start; DEBUG_F("Reading %d bytes, starting at block %Lu, disk offset %Lu\n", length, block, pos); if (!prom_seek(file->of_device, pos)) { DEBUG_F("prom_seek failed\n"); return 0; } return prom_read(file->of_device, buf, length); }
static int read_disk_block( struct boot_file_t *file, __u32 block, __u32 start, __u32 length, void *buf ) { __u16 fs_blocksize = INFO->blocksize == 0 ? REISERFS_OLD_BLOCKSIZE : INFO->blocksize; unsigned long long pos = (unsigned long long)block * (unsigned long long)fs_blocksize; pos += (unsigned long long)INFO->partition_offset + (unsigned long long)start; DEBUG_F( "Reading %u bytes, starting at block %u, disk offset %Lu\n", length, block, pos ); if (!prom_lseek( file->of_device, pos )) { DEBUG_F("prom_lseek failed\n"); return 0; } return prom_read( file->of_device, buf, length ); }
int prom_cngetc(dev_t dev) { unsigned char ch = '\0'; int l; #ifdef DDB static int nplus = 0; #endif while ((l = prom_read(prom_stdin(), &ch, 1)) != 1) /* void */; #ifdef DDB if (ch == '+') { if (nplus++ > 3) Debugger(); } else nplus = 0; #endif if (ch == '\r') ch = '\n'; return ch; }
/* * Receive a packet, including the ether header. * Return the total length received (or -1 on error). */ ssize_t netif_get(struct iodesc *desc, void *pkt, size_t maxlen, time_t timo) { struct of_dev *op; int tick0, tmo_ms; int len; op = ((struct netif *)desc->io_netif)->nif_devdata; #ifdef NETIF_DEBUG printf("netif_get: pkt=0x%x, maxlen=%d, tmo=%d\n", pkt, maxlen, timo); #endif tmo_ms = timo * 1000; tick0 = prom_ticks(); do { len = prom_read(op->handle, pkt, maxlen); } while ((len == -2 || len == 0) && (prom_ticks() - tick0 < tmo_ms)); #ifdef NETIF_DEBUG printf("netif_get: received len=%d\n", len); #endif if (len < 12) return -1; #ifdef NETIF_DEBUG { struct ether_header *eh = pkt; printf("dst: %s ", ether_sprintf(eh->ether_dhost)); printf("src: %s ", ether_sprintf(eh->ether_shost)); printf("type: 0x%x\n", eh->ether_type & 0xFFFF); } #endif return len; }
int read(int fd, void *buf, size_t count) { return prom_read((void *)fd, buf, count); }
/* * Handle a IP datagram addressed to our MAC address or to the link * layer broadcast address. Also respond to ARP requests. Generates * inetgrams as long as there's data and the mac level IP timeout timer * hasn't expired. As soon as there is no data, we try for * IBD_INPUT_ATTEMPTS for more, then exit the loop, even if there is time * left, since we expect to have data waiting for us when we're called, we just * don't know how much. * * We workaround slow proms (some proms have hard sleeps for as much as 3msec) * even though there are is data waiting. * * Returns the total number of MEDIA_LVL frames placed on the socket. * Caller is expected to free up the inetgram resources. */ static int ibd_input(int index) { struct inetgram *inp; ipoib_ptxhdr_t *eh; int frames = 0; /* successful frames */ int attempts = 0; /* failed attempts after success */ int16_t len = 0, data_len; uint32_t timeout, reltime; uint32_t pre_pr, post_pr; /* prom_read interval */ #ifdef DEBUG int failures = 0; /* total failures */ int total_attempts = 0; /* total prom_read */ int no_data = 0; /* no data in prom */ int arps = 0; /* arp requests processed */ uint32_t tot_pr = 0; /* prom_read time */ uint32_t tot_pc = 0; /* inetgram creation time */ uint32_t pre_pc; uint32_t now; #endif /* DEBUG */ if (!initialized) prom_panic("IPoIB device is not initialized."); if ((reltime = sockets[index].in_timeout) == 0) reltime = mac_state.mac_in_timeout; timeout = prom_gettime() + reltime; do { if (frames > IBD_MAX_FRAMES) { /* someone is trying a denial of service attack */ break; } /* * The following is being paranoid about possible bugs * where prom_read() returns a nonzero length, even when * it's not read a packet; it zeroes out the header to * compensate. Paranoia from calvin prom (V2) days. */ bzero(mac_state.mac_buf, sizeof (ipoib_ptxhdr_t)); /* * Prom_read() will return 0 or -2 if no data is present. A * return value of -1 means an error has occurred. We adjust * the timeout by calling the time spent in prom_read() "free". * prom_read() returns the number of bytes actually read, but * will only copy "len" bytes into our buffer. Adjust in * case the MTU is wrong. */ pre_pr = prom_gettime(); len = prom_read(mac_state.mac_dev, mac_state.mac_buf, mac_state.mac_mtu, 0, NETWORK); post_pr = prom_gettime(); timeout += (post_pr - pre_pr); #ifdef DEBUG tot_pr += (post_pr - pre_pr); total_attempts++; #endif /* DEBUG */ if (len > mac_state.mac_mtu) { dprintf("ibd_input: adjusting MTU %d -> %d\n", mac_state.mac_mtu, len); bkmem_free(mac_state.mac_buf, mac_state.mac_mtu); mac_state.mac_mtu = len; mac_state.mac_buf = bkmem_alloc(mac_state.mac_mtu); if (mac_state.mac_buf == NULL) { prom_panic("ibd_input: Cannot reallocate " "netbuf memory."); } len = 0; /* pretend there was no data */ } if (len == -1) { #ifdef DEBUG failures++; #endif /* DEBUG */ break; } if (len == 0 || len == -2) { if (frames != 0) attempts++; #ifdef DEBUG no_data++; #endif /* DEBUG */ continue; } eh = (ipoib_ptxhdr_t *)mac_state.mac_buf; if (eh->ipoib_rhdr.ipoib_type == ntohs(ETHERTYPE_IP) && len >= (sizeof (ipoib_ptxhdr_t) + sizeof (struct ip))) { int offset; #ifdef DEBUG pre_pc = prom_gettime(); #endif /* DEBUG */ inp = (struct inetgram *)bkmem_zalloc( sizeof (struct inetgram)); if (inp == NULL) { errno = ENOMEM; return (frames == 0 ? -1 : frames); } offset = sizeof (ipoib_ptxhdr_t); data_len = len - offset; inp->igm_mp = allocb(data_len, 0); if (inp->igm_mp == NULL) { errno = ENOMEM; bkmem_free((caddr_t)inp, sizeof (struct inetgram)); return (frames == 0 ? -1 : frames); } bcopy((caddr_t)(mac_state.mac_buf + offset), inp->igm_mp->b_rptr, data_len); inp->igm_mp->b_wptr += data_len; inp->igm_level = NETWORK_LVL; add_grams(&sockets[index].inq, inp); frames++; attempts = 0; #ifdef DEBUG tot_pc += prom_gettime() - pre_pc; #endif /* DEBUG */ continue; } if (eh->ipoib_rhdr.ipoib_type == ntohs(ETHERTYPE_ARP) && len >= sizeof (struct arp_packet)) { struct in_addr ip; struct ibd_arp *ea; #ifdef DEBUG printf("ibd_input: ARP message received\n"); arps++; #endif /* DEBUG */ ea = (struct ibd_arp *)(mac_state.mac_buf + sizeof (ipoib_ptxhdr_t)); if (ea->arp_pro != ntohs(ETHERTYPE_IP)) continue; ipv4_getipaddr(&ip); ip.s_addr = ntohl(ip.s_addr); if (ea->arp_op == ntohs(ARPOP_REQUEST) && ip.s_addr != INADDR_ANY && (bcmp((caddr_t)ea->arp_tpa, (caddr_t)&ip, sizeof (struct in_addr)) == 0)) { ea->arp_op = htons(ARPOP_REPLY); bcopy((caddr_t)&ea->arp_sha, (caddr_t)&eh->ipoib_dest, IPOIB_ADDRL); bcopy((caddr_t)&ea->arp_sha, (caddr_t)&ea->arp_tha, IPOIB_ADDRL); bcopy((caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa, sizeof (struct in_addr)); bcopy(mac_state.mac_addr_buf, (caddr_t)&ea->arp_sha, mac_state.mac_addr_len); bcopy((caddr_t)&ip, (caddr_t)ea->arp_spa, sizeof (struct in_addr)); (void) prom_write(mac_state.mac_dev, mac_state.mac_buf, sizeof (struct arp_packet), 0, NETWORK); /* don't charge for ARP replies */ timeout += reltime; } } } while (attempts < IBD_INPUT_ATTEMPTS && #ifdef DEBUG (now = prom_gettime()) < timeout); #else prom_gettime() < timeout); #endif /* DEBUG */ #ifdef DEBUG printf("ibd_input(%d): T/S/N/A/F/P/M: %d/%d/%d/%d/%d/%d/%d " "T/O: %d < %d = %s\n", index, total_attempts, frames, no_data, arps, failures, tot_pr, tot_pc, now, timeout, (now < timeout) ? "TRUE" : "FALSE"); #endif /* DEBUG */ return (frames); }
/* * Common ARP code. Broadcast the packet and wait for the right response. * * If arp is called for, caller expects a hardware address in the * source hardware address (sha) field of the "out" argument. * * IPoIB does not support RARP (see ibd_revarp()). * * Returns TRUE if transaction succeeded, FALSE otherwise. * * The timeout argument is the number of milliseconds to wait for a * response. An infinite timeout can be specified as 0xffffffff. */ static int ibd_comarp(struct arp_packet *out, uint32_t timeout) { struct arp_packet *in = (struct arp_packet *)mac_state.mac_buf; int count, time, feedback, len, delay = 2; char *ind = "-\\|/"; struct in_addr tmp_ia; uint32_t wait_time; bcopy((caddr_t)&ibdbroadcastaddr, (caddr_t)&out->arp_eh.ipoib_dest, IPOIB_ADDRL); out->arp_ea.arp_hrd = htons(ARPHRD_IB); out->arp_ea.arp_pro = htons(ETHERTYPE_IP); out->arp_ea.arp_hln = IPOIB_ADDRL; out->arp_ea.arp_pln = sizeof (struct in_addr); bcopy(mac_state.mac_addr_buf, (caddr_t)&out->arp_ea.arp_sha, IPOIB_ADDRL); ipv4_getipaddr(&tmp_ia); tmp_ia.s_addr = htonl(tmp_ia.s_addr); bcopy((caddr_t)&tmp_ia, (caddr_t)out->arp_ea.arp_spa, sizeof (struct in_addr)); feedback = 0; wait_time = prom_gettime() + timeout; for (count = 0; timeout == ~0U || prom_gettime() < wait_time; count++) { if (count == IBD_WAITCNT) { /* * Since IPoIB does not support RARP (see ibd_revarp), * we know that out->arp_ea.arp_op == ARPOP_REQUEST. */ bcopy((caddr_t)out->arp_ea.arp_tpa, (caddr_t)&tmp_ia, sizeof (struct in_addr)); printf("\nRequesting MAC address for: %s\n", inet_ntoa(tmp_ia)); } (void) prom_write(mac_state.mac_dev, (caddr_t)out, sizeof (*out), 0, NETWORK); if (count >= IBD_WAITCNT) printf("%c\b", ind[feedback++ % 4]); /* activity */ time = prom_gettime() + (delay * 1000); /* broadcast delay */ while (prom_gettime() <= time) { len = prom_read(mac_state.mac_dev, mac_state.mac_buf, mac_state.mac_mtu, 0, NETWORK); if (len < sizeof (struct arp_packet)) continue; if (in->arp_ea.arp_pro != ntohs(ETHERTYPE_IP)) continue; /* * Since IPoIB does not support RARP (see ibd_revarp), * we know that out->arp_ea.arp_op == ARPOP_REQUEST. */ if (in->arp_eh.ipoib_rhdr.ipoib_type != ntohs(ETHERTYPE_ARP)) continue; if (in->arp_ea.arp_op != ntohs(ARPOP_REPLY)) continue; if (bcmp((caddr_t)in->arp_ea.arp_spa, (caddr_t)out->arp_ea.arp_tpa, sizeof (struct in_addr)) != 0) continue; if (boothowto & RB_VERBOSE) { bcopy((caddr_t)in->arp_ea.arp_spa, (caddr_t)&tmp_ia, sizeof (struct in_addr)); printf("Found %s @ %s\n", inet_ntoa(tmp_ia), ibd_print(&in->arp_ea.arp_sha)); } /* copy hardware addr into "out" for caller */ bcopy((caddr_t)&in->arp_ea.arp_sha, (caddr_t)&out->arp_ea.arp_sha, IPOIB_ADDRL); return (TRUE); } delay = delay * 2; /* Double the request delay */ if (delay > 64) /* maximum delay is 64 seconds */ delay = 64; } return (FALSE); }