/*
**************************************************************************
*
* Boot-ROM-Code to load an operating system across a TCP/IP network.
*
* Module: boot.c
* Purpose: Perform the actual booting process
* Entries: do_boot
*
**************************************************************************
*
* Copyright (C) 1995-2003 Gero Kuhlmann <gero@gkminix.han.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: boot.c,v 1.6 2003/01/25 23:29:41 gkminix Exp $
*/
#include <general.h>
#include <kernel/net.h>
#include <kernel/arpa.h>
#include <kernel/romlib.h>
#include <pxe/common.h>
#include <pxe/pxegeneral.h>
#include "bootpriv.h"
#include "menu.h"
#include "load.h"
/*
**************************************************************************
*
* Variables local to this module
*/
static jmp_buf restartenv; /* setjmp buffer for restart */
/*
**************************************************************************
*
* Print an IP number. Note that the IP address should be in network
* order.
*/
static void printip(ip)
t_ipaddr ip;
{
register unsigned char *cp = (unsigned char *)&ip;
printf("%u.%u.%u.%u", cp[0], cp[1], cp[2], cp[3]);
}
/*
**************************************************************************
*
* Set parameters from BOOTP record
*/
static int setparams()
{
register unsigned char *cp;
register int len;
unsigned char *sname;
int snamlen;
int overload = 0;
cur_bootp_buf = BOOTP_REPLY;
memset(&ldparams, 0, sizeof(ldparams));
/* Get the overloading tag */
if ((cp = get_vend(VEND_OVERLOAD)) != NULL)
overload = *(cp + 1);
/* Determine the IP address of the TFTP server */
if ((cp = get_vend(VEND_SERVER)) != NULL)
ldparams.tftp.server = *((t_ipaddr *)(cp + 1));
else
ldparams.tftp.server = bootp_bufs[BOOTP_REPLY]->bp_siaddr;
if (ldparams.tftp.server == n_IP_ANY)
return(PXENV_STATUS_DHCP_NO_IP_ADDR);
/* Determine name of server the boot image file will come from */
if ((cp = get_vend(VEND_TFTPNAME)) != NULL) {
sname = cp + 1;
snamlen = *cp;
} else if (!(overload & VEND_OVR_SNAME)) {
sname = bootp_bufs[BOOTP_REPLY]->bp_sname;
snamlen = BOOTP_SNAME_SIZE;
} else
sname = NULL;
/* Determine name of boot image file to load */
if ((cp = get_vend(VEND_BOOTFILE)) != NULL) {
len = *cp;
if (len > sizeof(ldparams.tftp.filename))
len = sizeof(ldparams.tftp.filename);
memcpy(ldparams.tftp.filename, cp + 1, len);
} else if (!(overload & VEND_OVR_FILE))
memcpy(ldparams.tftp.filename, bootp_bufs[BOOTP_REPLY]->bp_file,
sizeof(ldparams.tftp.filename));
if (ldparams.tftp.filename[0] == '\0')
return(PXENV_STATUS_DHCP_NO_FILE);
/* Get any router information */
if ((cp = get_vend(VEND_ROUTER)) != NULL)
ldparams.tftp.gateway = *((t_ipaddr *)(cp + 1));
/* Print some of the information we got so far */
printf("\n\nLocal IP: "); printip(myipaddr);
printf("\nServer IP: "); printip(ldparams.tftp.server);
if (sname != NULL)
printf(" (%ls)", sname, snamlen);
if (ldparams.tftp.gateway != n_IP_ANY) {
printf("\nGateway IP: ");
printip(ldparams.tftp.gateway);
}
printf("\n");
return(PXENV_STATUS_SUCCESS);
}
/*
**************************************************************************
*
* Actually perform the booting process by first calling the BOOTP client,
* and then loading the operating system using TFTP. This routine gets
* called from the assembler startup code.
*
*/
int do_boot()
{
int ret;
/* Wait some seconds for the network card to settle down */
set_timeout(3);
while (!chk_timeout()) ;
/* Now start the network booting process */
if ((ret = bootp()) == PXENV_STATUS_SUCCESS) {
#ifndef NOMENU
if (domenu() != MENU_ABORT) {
#endif
while ((ret = setparams()) == PXENV_STATUS_SUCCESS) {
if ((ret = load(FALSE)) != PXENV_STATUS_SUCCESS)
break;
printf("\n\nStarting image...\n");
setjmp(&restartenv);
if (!exec_image(ldparams.mode,
ldparams.exec,
ldparams.header,
bootp_bufs[BOOTP_REPLY],
ldparams.drive)) {
ret = PXENV_STATUS_SUCCESS;
break;
}
}
#ifndef NOMENU
}
#endif
}
return(ret);
}
/*
**************************************************************************
*
* Restart TFTP PXE function
*/
int pxe_restart(params)
t_tftp_read_file *params;
{
register int ret = PXENV_STATUS_FAILURE;
memset(&ldparams, 0, sizeof(ldparams));
memcpy(&ldparams.tftp, params, sizeof(ldparams.tftp));
if ((ret = load(TRUE)) == PXENV_STATUS_SUCCESS)
/*
* We have to use longjump here to jump back to the original
* bootrom loader code. Otherwise, the bootrom stack will
* overflow with multiple calls of this routine.
*/
longjmp(&restartenv, 0);
return(ret);
}
/*
**************************************************************************
*
* Return BOOTP/DHCP information
*/
int pxe_get_binl_info(params)
t_gen_get_binl_info *params;
{
register unsigned char *cp = NULL;
unsigned int len, limit, ret;
ret = PXENV_STATUS_FAILURE;
if (params->packet_type >= GEN_PACKET_DHCP_DISCOVER &&
params->packet_type <= GEN_PACKET_BINL_REPLY) {
cur_bootp_buf = params->packet_type - 1;
cp = (unsigned char *)(bootp_bufs[cur_bootp_buf]);
limit = bootp_sizes[cur_bootp_buf];
len = get_vend(VEND_END) - cp;
if ((params->buffer_offset + params->buffer_segment +
params->buffer_size) == 0) {
params->buffer_size = len;
params->buffer_offset = (unsigned int)cp;
params->buffer_segment = getds();
params->buffer_limit = limit;
ret = PXENV_STATUS_SUCCESS;
} else if (params->buffer_size >= len) {
fmemcpy(params->buffer_offset, params->buffer_segment, cp, len);
params->buffer_size = len;
params->buffer_limit = limit;
ret = PXENV_STATUS_SUCCESS;
}
}
return(ret);
}
syntax highlighted by Code2HTML, v. 0.9.1