Example #1
0
/** Set the current PXE handle.
 * @param handle        Handle to set to. If NULL, current will be closed.
 * @return              Status code describing the result of the operation. */
static status_t set_current_handle(pxe_handle_t *handle) {
  if (current_pxe_handle) {
    pxenv_tftp_close_t close;

    pxe_call(PXENV_TFTP_CLOSE, &close);
    current_pxe_handle = NULL;
  }

  if (handle) {
    pxe_device_t *device = container_of(handle->handle.mount, pxe_device_t, mount);
    pxenv_tftp_open_t open;

    strcpy((char *)open.filename, handle->path);
    memcpy(&open.server_ip, &device->net.server_ip, sizeof(open.server_ip));
    memcpy(&open.gateway_ip, &device->net.gateway_ip, sizeof(open.gateway_ip));
    open.udp_port = cpu_to_be16(device->net.server_port);
    open.packet_size = PXENV_TFTP_PACKET_SIZE;

    if (pxe_call(PXENV_TFTP_OPEN, &open) != PXENV_EXIT_SUCCESS || open.status) {
      if (open.status == PXENV_STATUS_TFTP_NOT_FOUND) {
        return STATUS_NOT_FOUND;
      } else {
        dprintf("pxe: open request for '%s' failed: 0x%x\n", handle->path, open.status);
        return STATUS_DEVICE_ERROR;
      }
    }

    handle->packet_size = open.packet_size;
    handle->packet_number = 0;

    current_pxe_handle = handle;
  }

  return STATUS_SUCCESS;
}
Example #2
0
/**
 * Shut down PXE before booting an OS
 */
static void shutdown_pxe(void) {
  if (pxe_call(PXENV_UNDI_SHUTDOWN, (void *)BIOS_MEM_BASE) != PXENV_EXIT_SUCCESS) {
    dprintf("pxe: warning: PXENV_UNDI_SHUTDOWN failed\n");
  }

  if (pxe_call(PXENV_UNLOAD_STACK, (void *)BIOS_MEM_BASE) != PXENV_EXIT_SUCCESS) {
    dprintf("pxe: warning: PXENV_UNLOAD_STACK failed\n");
  }

  if (pxe_call(PXENV_STOP_UNDI, (void *)BIOS_MEM_BASE) != PXENV_EXIT_SUCCESS) {
    dprintf("pxe: warning: PXENV_STOP_UNDI failed\n");
  }
}
Example #3
0
static void gpxecmd(const char **args)
{
    char *q;
    struct s_PXENV_FILE_EXEC *fx;

    fx = lmalloc(sizeof *fx);
    if (!fx)
	return;

    q = (char *)(fx + 1);

    fx->Status = 1;
    fx->Command.offs = OFFS(q);
    fx->Command.seg = SEG(q);

    while (*args) {
	q = stpcpy(q, *args);
	*q++ = ' ';
	args++;
    }
    *--q = '\0';

    pxe_call(PXENV_FILE_EXEC, fx);

    /* This should not return... */
}
Example #4
0
/**
 * Get a fresh packet from a gPXE socket
 * @param: inode -> Inode pointer
 *
 */
static void gpxe_get_packet(struct inode *inode)
{
    struct pxe_pvt_inode *socket = PVT(inode);
    static __lowmem struct s_PXENV_FILE_READ file_read;
    int err;

    while (1) {
        file_read.FileHandle  = socket->tftp_remoteport;
        file_read.Buffer      = FAR_PTR(packet_buf);
        file_read.BufferSize  = PKTBUF_SIZE;
        err = pxe_call(PXENV_FILE_READ, &file_read);
        if (!err)  /* successed */
            break;

        if (file_read.Status != PXENV_STATUS_TFTP_OPEN)
	    kaboom();
    }

    memcpy(socket->tftp_pktbuf, packet_buf, file_read.BufferSize);

    socket->tftp_dataptr   = socket->tftp_pktbuf;
    socket->tftp_bytesleft = file_read.BufferSize;
    socket->tftp_filepos  += file_read.BufferSize;

    if (socket->tftp_bytesleft == 0)
        inode->size = socket->tftp_filepos;

    /* if we're done here, close the file */
    if (inode->size > socket->tftp_filepos)
        return;

    /* Got EOF, close it */
    socket->tftp_goteof = 1;
    gpxe_close_file(inode);
}
Example #5
0
/* Caller must leave room for ethernet, ip, and udp headers in front!! */
ssize_t
pxesendudp(struct iodesc *d, void *pkt, size_t len)
{
	t_PXENV_UDP_WRITE *uw = (void *) pxe_command_buf;

	uw->status = 0;

	uw->ip = d->destip.s_addr;
	uw->gw = gateip.s_addr;
	uw->src_port = d->myport;
	uw->dst_port = d->destport;
	uw->buffer_size = len;
	uw->buffer.segment = VTOPSEG(pkt);
	uw->buffer.offset = VTOPOFF(pkt);

	pxe_call(PXENV_UDP_WRITE);

	if (uw->status != PXENV_STATUS_SUCCESS) {
		/* XXX This happens a lot; it shouldn't. */
		if (uw->status != PXENV_STATUS_FAILURE)
			printf("sendudp: PXENV_UDP_WRITE failed: 0x%x\n",
			    uw->status);
		return -1;
	}

	return len;
}
Example #6
0
int
pxe_read(IP4_t * src, UDP_PORT_t * port,
    void * buf, int len, int block)
{
	t_PXENV_UDP_READ * pxe_read;

	bzero (pxebuf, sizeof(t_PXENV_UDP_READ));
	pxe_read = (t_PXENV_UDP_READ *)pxebuf;

retry:

	pxe_read->dest_ip = htonl(*src);
        pxe_read->d_port = htons(*port);
        pxe_read->buffer_size = len;
        pxe_read->buffer.segment = SEG(buf);
        pxe_read->buffer.offset = OFF(buf);

        pxe_op = (uint16_t)PXENV_UDP_READ;
        pxe_addr = (uint16_t *)pxe_read;

        if (pxe_call() != 0) {
		if (block)
			goto retry;
                return(1);
	}

	*src = ntohl(pxe_read->src_ip);
	*port = ntohs(pxe_read->s_port);
	
	return(0);
}
Example #7
0
int
pxe_write(IP4_t dst, UDP_PORT_t port,
    void * buf, int len)
{
	t_PXENV_UDP_WRITE * pxe_write;
	int i = 0;

	bzero (pxebuf, sizeof(t_PXENV_UDP_WRITE));
	pxe_write = (t_PXENV_UDP_WRITE *)pxebuf;

retry:

	pxe_write->ip = htonl(dst);
        pxe_write->dst_port = htons(port);
        pxe_write->src_port = htons(port);
        pxe_write->buffer_size = len;
        pxe_write->buffer.segment = SEG(buf);
        pxe_write->buffer.offset = OFF(buf);

        pxe_op = (uint16_t)PXENV_UDP_WRITE;
        pxe_addr = (uint16_t *)pxe_write;

        if (pxe_call() != 0) {
		i++;
		if (i < 10)
			goto retry;
                return(1);
        }

	return(0);
}
Example #8
0
static void gpxe_close_file(struct inode *inode)
{
    struct pxe_pvt_inode *socket = PVT(inode);
    static __lowmem struct s_PXENV_FILE_CLOSE file_close;

    file_close.FileHandle = socket->tftp_remoteport;
    pxe_call(PXENV_FILE_CLOSE, &file_close);
}
Example #9
0
/**
 * Get the BOOTP reply packet.
 *
 * @return              Pointer to BOOTP reply packet.
 */
static bootp_packet_t *get_bootp_packet(void) {
  pxenv_get_cached_info_t ci;

  /* Obtain the BOOTP reply packet. */
  ci.packet_type = PXENV_PACKET_TYPE_CACHED_REPLY;
  ci.buffer = 0;
  ci.buffer_size = 0;
  if (pxe_call(PXENV_GET_CACHED_INFO, &ci) != PXENV_EXIT_SUCCESS)
    boot_error("Failed to get PXE BOOTP packet (0x%x)", ci.status);

  return (bootp_packet_t *)segoff_to_linear(ci.buffer);
}
Example #10
0
/**
 * Read the next packet from a TFTP file.
 *
 * @note                Reads to BIOS_MEM_BASE.
 * @param handle        Handle to read from.
 * @return              Status code describing the result of the operation.
 */
static status_t read_packet(pxe_handle_t *handle) {
  pxenv_tftp_read_t read;

  read.buffer = BIOS_MEM_BASE;
  read.buffer_size = handle->packet_size;

  if (pxe_call(PXENV_TFTP_READ, &read) != PXENV_EXIT_SUCCESS || read.status) {
    dprintf("pxe: reading packet %u in '%s' failed: 0x%x\n", handle->packet_number, handle->path, read.status);
    return STATUS_DEVICE_ERROR;
  }

  handle->packet_number++;
  return STATUS_SUCCESS;
}
Example #11
0
int pxe_close(void)
{
	t_PXENV_UDP_CLOSE * pxe_close;

	bzero (pxebuf, sizeof(t_PXENV_UDP_CLOSE));
	pxe_close = (t_PXENV_UDP_CLOSE *)pxebuf;

        pxe_op = (uint16_t)PXENV_UDP_CLOSE;
        pxe_addr = (uint16_t *)pxe_close;

        if (pxe_call() != 0) {
#ifndef SILENT
                printf("PXE UDP close failed\n");
#endif
                return(1);
        }

	return(0);
}
Example #12
0
/**
 * Open a path on the filesystem.
 *
 * @param mount         Mount to open from.
 * @param path          Path to file/directory to open (can be modified).
 * @param from          Handle on this FS to open relative to.
 * @param _handle       Where to store pointer to opened handle.
 * @return              Status code describing the result of the operation.
 */
static status_t pxe_fs_open_path(fs_mount_t *mount, char *path, fs_handle_t *from, fs_handle_t **_handle) {
  pxe_device_t *device = container_of(mount, pxe_device_t, mount);
  pxenv_tftp_get_fsize_t fsize;
  pxe_handle_t *handle;
  size_t len;
  status_t ret;

  if (from) { return STATUS_NOT_SUPPORTED; }

  len = strlen(path);
  if (len >= PXENV_TFTP_PATH_SIZE) { return STATUS_NOT_FOUND; }

  /* Get the file size. I'm not actually sure whether it's necessary to close
   * the current handle beforehand, but I'm doing it to be on the safe side. */
  set_current_handle(NULL);
  strcpy((char *)fsize.filename, path);
  memcpy(&fsize.server_ip, &device->net.server_ip, sizeof(fsize.server_ip));
  memcpy(&fsize.gateway_ip, &device->net.gateway_ip, sizeof(fsize.gateway_ip));

  if (pxe_call(PXENV_TFTP_GET_FSIZE, &fsize) != PXENV_EXIT_SUCCESS || fsize.status) {
    if (fsize.status == PXENV_STATUS_TFTP_NOT_FOUND) {
      return STATUS_NOT_FOUND;
    } else {
      dprintf("pxe: file size request for '%s' failed: 0x%x\n", path, fsize.status);
      return STATUS_DEVICE_ERROR;
    }
  }

  handle = malloc(sizeof(*handle) + len + 1);
  fs_handle_init(&handle->handle, mount, FILE_TYPE_REGULAR, fsize.file_size);
  strcpy(handle->path, path);

  /* Try to open the file as the current. */
  ret = set_current_handle(handle);
  if (ret != STATUS_SUCCESS) {
    free(handle);
    return ret;
  }

  *_handle = &handle->handle;
  return STATUS_SUCCESS;
}
Example #13
0
int
pxe_open(void)
{
	t_PXENV_UDP_OPEN * pxe_open;

	bzero (pxebuf, sizeof(t_PXENV_UDP_OPEN));
	pxe_open = (t_PXENV_UDP_OPEN *)pxebuf;

        pxe_op = (uint16_t)PXENV_UDP_OPEN;
        pxe_addr = (uint16_t *)pxe_open;

	pxe_open->src_ip = bootp->yip;

        if (pxe_call() != 0) {
#ifndef SILENT
                printf("PXE UDP open failed\n");
#endif
                return(1);
        }

	return(0);
}
Example #14
0
int
pxe_netif_open()
{
	t_PXENV_UDP_OPEN *uo = (void *) pxe_command_buf;

#ifdef NETIF_DEBUG
	printf("pxe_netif_open()\n");
#endif
	if (!pxe_inited) {
		if (pxe_init(0) != 0)
			return -1;
		pxe_inited = 1;
	}
	/* BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif)); */

	bzero(uo, sizeof(*uo));

	uo->src_ip = bootplayer.yip;

	pxe_call(PXENV_UDP_OPEN);

	if (uo->status != PXENV_STATUS_SUCCESS) {
		printf("\npxe_netif_open: PXENV_UDP_OPEN failed: 0x%x\n",
		    uo->status);
		return -1;
	}

	bcopy(bootplayer.CAddr, desc.myea, ETHER_ADDR_LEN);
	bootmac = bootplayer.CAddr;

	/*
	 * Since the PXE BIOS has already done DHCP, make sure we
	 * don't reuse any of its transaction IDs.
	 */
	desc.xid = bootplayer.ident;

	return 0;
}
Example #15
0
/**
 * Open a url using gpxe
 *
 * @param:inode, the inode to store our state in
 * @param:url, the url we want to open
 *
 * @out: open_file_t structure, stores in file->open_file
 * @out: the lenght of this file, stores in file->file_len
 *
 */
void gpxe_open(struct inode *inode, const char *url)
{
    static __lowmem struct s_PXENV_FILE_OPEN file_open;
    static char lowurl[2*FILENAME_MAX];
    struct pxe_pvt_inode *socket = PVT(inode);
    int err;

    socket->tftp_pktbuf = malloc(PKTBUF_SIZE);
    if (!socket->tftp_pktbuf)
	return;

    snprintf(lowurl, sizeof lowurl, "%s", url);
    file_open.Status        = PXENV_STATUS_BAD_FUNC;
    file_open.FileName      = FAR_PTR(lowurl);
    err = pxe_call(PXENV_FILE_OPEN, &file_open);
    if (err)
	return; 

    socket->fill_buffer = gpxe_get_packet;
    socket->close = gpxe_close_file;
    socket->tftp_remoteport = file_open.FileHandle;
    inode->size = -1; /* This is not an error */
}
Example #16
0
/*
 * Receive a UDP packet and validate it for us.
 * Caller leaves room for the headers (Ether, IP, UDP).
 */
ssize_t
pxereadudp(struct iodesc *d, void *pkt, size_t len, time_t tleft)
{
	t_PXENV_UDP_READ *ur = (void *) pxe_command_buf;
	struct udphdr *uh;
	struct ip *ip;

	uh = (struct udphdr *)pkt - 1;
	ip = (struct ip *)uh - 1;

	bzero(ur, sizeof(*ur));

	ur->dest_ip = d->myip.s_addr;
	ur->d_port = d->myport;
	ur->buffer_size = len;
	ur->buffer.segment = VTOPSEG(pkt);
	ur->buffer.offset = VTOPOFF(pkt);

	/* XXX Timeout unused. */

	pxe_call(PXENV_UDP_READ);

	if (ur->status != PXENV_STATUS_SUCCESS) {
		/* XXX This happens a lot; it shouldn't. */
		if (ur->status != PXENV_STATUS_FAILURE)
			printf("readudp: PXENV_UDP_READ_failed: 0x%0x\n",
			    ur->status);
		return -1;
	}

	ip->ip_src.s_addr = ur->src_ip;
	uh->uh_sport = ur->s_port;
	uh->uh_dport = d->myport;

	return ur->buffer_size;
}
Example #17
0
int
pxe_init(IP4_t * myaddr, int * sendsize)
{
	pxenv_t * pxe;
	pxe_t * pxe2;
	t_PXENV_GET_CACHED_INFO * pxe_cache;
	t_PXENV_UNDI_GET_INFORMATION * pxe_info;

	bios_pxe();

	if (pxe_op != PXE_VN)
		return(1);

	/* Find PXENV+ structure */

	pxe = (pxenv_t *)((uintptr_t)((pxe_seg << 4) + pxe_off));

	/* Find !PXE structure */

	pxe2 = (pxe_t *)((uintptr_t)((pxe->PXEPtr.segment << 4) +
            pxe->PXEPtr.offset));

#ifndef SILENT
	printf("PXE version: %d.%d entry: %x:%x\n", pxe->Version >> 8,
	    pxe->Version & 0xFF, pxe2->EntryPointSP.segment,
	    pxe2->EntryPointSP.offset);
#endif

        /* Save the PXE entry point */

	pxe_seg = pxe2->EntryPointSP.segment;
	pxe_off = pxe2->EntryPointSP.offset;

	/* Get UNDI info */

	bzero (pxebuf, sizeof(pxebuf));
	pxe_info = (t_PXENV_UNDI_GET_INFORMATION *)pxebuf;
 
	pxe_op = (uint16_t)PXENV_UNDI_GET_INFORMATION;
        pxe_addr = (uint16_t *)pxe_info;

        if (pxe_call() != 0) {
#ifndef SILENT
                printf("PXE get UNDI info failed\n");
#endif
                return(1);
        }

#ifndef SILENT
	printf("pxe0 at 0x%x irq %d\n", pxe_info->BaseIo, pxe_info->IntNumber);
#endif

	*sendsize = pxe_info->TxBufCt;

	/* Now find our IP address */

	bzero (pxebuf, sizeof(pxebuf));
	pxe_cache = (t_PXENV_GET_CACHED_INFO *)pxebuf;
	pxe_cache->PacketType = PXENV_PACKET_TYPE_BINL_REPLY;
 
	pxe_op = (uint16_t)PXENV_GET_CACHED_INFO;
        pxe_addr = (uint16_t *)pxe_cache;

        pxe_call();

        if (pxe_call() != 0) {
#ifndef SILENT
                printf("PXE get cache failed\n");
#endif
                return(1);
        }

        bootp = (BOOTPLAYER *)((uintptr_t)((pxe_cache->Buffer.segment << 4) +
            pxe_cache->Buffer.offset));

#ifndef SILENT
	printf("My IP address: %d.%d.%d.%d\n", IP_ARGS(ntohl(bootp->yip)));
	printf("My eth address: %02x:%02x:%02x:%02x:%02x:%02x\n",
	    bootp->CAddr[0], bootp->CAddr[1], bootp->CAddr[2], bootp->CAddr[3],
	    bootp->CAddr[4], bootp->CAddr[5]);
#endif

	*myaddr = ntohl(bootp->yip);

	return (0);
}