2011-11-16, 03:10
I was asked by private message to post a how-to on using etherboot to wol a server.
I have etherboot installed on a USB key that runs just after the BIOS, sends a WOL packet to wake-up my file server, then continues to boot in Ubuntu off the internal harddrive then into XBMC.
I did this to be able to send the WOL packet to the server earlier and give it more time to boot before XBMC starts. The only other ways is to use a Ubuntu init script, but this would only run just before XBMC.
Normally Etherboot is used for a pxe remote boot, but I use it only to send the wol packet, nothing else.
I am no longer using this approach since I now put my server to sleep instead of doing a full boot.
I am posting what I did before, but I can't be sure it still works with the updates that have been made to the Etherboot GIT since the last time I built this. If you have trouble building or getting it to work, let me know, I check what version I previously used, that should still be pullable from git.
Other thing to mention is that Etherboot has a very limited set of ethernet drivers.
Here it goes, did this under ubuntu:
Need some support software
Clone the git etherboot code
Replace /src/core/main.cpp with
Add src/usr/wol.c and src/include/usr/wol.h. You can get the code from
http://git.etherboot.org/contrib.git/tre.../wakeonlan or alternately below.
Compile
Put on your usb key using, change sdx accordingly for your usb key
Change you BIOS to boot from the USB key then hdd second.
wol.c
wol.h
I have etherboot installed on a USB key that runs just after the BIOS, sends a WOL packet to wake-up my file server, then continues to boot in Ubuntu off the internal harddrive then into XBMC.
I did this to be able to send the WOL packet to the server earlier and give it more time to boot before XBMC starts. The only other ways is to use a Ubuntu init script, but this would only run just before XBMC.
Normally Etherboot is used for a pxe remote boot, but I use it only to send the wol packet, nothing else.
I am no longer using this approach since I now put my server to sleep instead of doing a full boot.
I am posting what I did before, but I can't be sure it still works with the updates that have been made to the Etherboot GIT since the last time I built this. If you have trouble building or getting it to work, let me know, I check what version I previously used, that should still be pullable from git.
Other thing to mention is that Etherboot has a very limited set of ethernet drivers.
Here it goes, did this under ubuntu:
Need some support software
Code:
apt-get install git-core, syslinux
Clone the git etherboot code
Code:
git clone git://git.etherboot.org/scm/gpxe.git
Replace /src/core/main.cpp with
Code:
/**************************************************************************
gPXE - Network Bootstrap Program
Literature dealing with the network protocols:
ARP - RFC826
RARP - RFC903
UDP - RFC768
BOOTP - RFC951, RFC2132 (vendor extensions)
DHCP - RFC2131, RFC2132 (options)
TFTP - RFC1350, RFC2347 (options), RFC2348 (blocksize), RFC2349 (tsize)
RPC - RFC1831, RFC1832 (XDR), RFC1833 (rpcbind/portmapper)
NFS - RFC1094, RFC1813 (v3, useful for clarifications, not implemented)
IGMP - RFC1112
**************************************************************************/
#include <stdio.h>
#include <gpxe/init.h>
#include <gpxe/features.h>
#include <gpxe/shell.h>
#include <gpxe/shell_banner.h>
#include <gpxe/image.h>
#include <gpxe/timer.h>
#include <unistd.h>
#include <usr/autoboot.h>
#include <config/general.h>
#include <string.h>
#include <usr/wol.h>
#define NORMAL "\033[0m"
#define BOLD "\033[1m"
#define CYAN "\033[36m"
/**
* Main entry point
*
* @ret rc Return status code
*/
__asmcall int main ( void ) {
char server_adr[6] = {0x00,0x16,0xe6,0xDA,0x46,0x80};
// struct feature *feature;
/* Some devices take an unreasonably long time to initialise */
/* printf ( PRODUCT_SHORT_NAME " initialising devices...\n" ); */
initialise();
startup();
/* printf ( NORMAL "\n\n" PRODUCT_NAME "\n" BOLD "gPXE " VERSION
NORMAL " -- Open Source Boot Firmware -- "
CYAN "http://etherboot.org" NORMAL "\n"
"Features:" );
for_each_table_entry ( feature, FEATURES )
printf ( " %s", feature->name );
printf ( "\n" );
shell();
sleep(30);
mdelay(100);
*/
printf("Waking MythTV backend server.......\n");
wakeup_server(server_adr);
wakeup_server(server_adr);
wakeup_server(server_adr);
wakeup_server(server_adr);
wakeup_server(server_adr);
// shell();
// mdelay(15000);
shutdown(SHUTDOWN_EXIT | shutdown_exit_flags);
return 0;
}
Add src/usr/wol.c and src/include/usr/wol.h. You can get the code from
http://git.etherboot.org/contrib.git/tre.../wakeonlan or alternately below.
Compile
Code:
cd src
make
Put on your usb key using, change sdx accordingly for your usb key
Code:
cat bin/gxpe.usb > /dev/sdx
Change you BIOS to boot from the USB key then hdd second.
wol.c
Code:
/*
* Copyright (C) 2008 William Stewart.
*
* 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.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <byteswap.h>
#include <gpxe/features.h>
#include <gpxe/netdevice.h>
#include <gpxe/if_ether.h>
#include <gpxe/iobuf.h>
#include <usr/ifmgmt.h>
#include <usr/wol.h>
#include <gpxe/timer.h>
#include <unistd.h>
/** @file
*
* Wake on lan
*
*/
/**
* Boot from a network device
*
* @v netdev Network device
* @ret rc Return status code
*/
#define debug 0
int wakeup_server(char *server_adr)
{
int rc, i,j;
unsigned char *buf;
uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
unsigned int len;
struct io_buffer *iobuf;
struct ethhdr *ethhdr;
struct net_device *netdev;
for_each_netdev ( netdev ) {
break;
}
if (netdev == NULL)
{
printf("Could not find netdev\n");
return 1;
}
/* Open device and display device status */
if ( (ifopen ( netdev ) ) != 0 )
{
printf("Could not open netdev\n");
return 1;
}
/* Create outgoing I/O buffer */
iobuf = alloc_iob ((ETH_HLEN + WOL_MSG_LEN)*2);
if (!iobuf)
{
printf("Could not allocate iob\n");
return 1;
}
ethhdr = iob_put(iobuf, sizeof(*ethhdr));
/* Build Ethernet header */
memcpy (ethhdr->h_dest, eth_broadcast, ETH_ALEN );
memcpy (ethhdr->h_source, netdev->ll_addr, ETH_ALEN );
ethhdr->h_protocol = htons (0x0842);
buf = iob_put (iobuf, WOL_MSG_LEN);
/* Build the message to send - 6 x 0xff then 16 x dest address */
len =0;
for (i = 0; i < 6; i++)
buf[len++] = 0xff;
for (j = 0; j < 16; j++)
for (i = 0; i < 6; i++)
buf[len++] = server_adr[i];
if (debug)
printf("wakeup_server sending %x %x %x %x %x %x\n", (int)server_adr[0], (int)server_adr[1], (int)server_adr[2], (int)server_adr[3], (int)server_adr[4], (int)server_adr[5]);
rc = netdev_tx (netdev, iobuf);
if (rc !=0)
printf("Failed to transmit WOL packet\n");
/* Give the controller a chance to send it before checking */
mdelay(300);
netdev_poll(netdev);
if (debug)
{
ifstat(netdev);
printf("sent wol packet\n");
}
return 0;
}
wol.h
Code:
#ifndef _USR_WOL_H
#define _USR_WOL_H
/** @file
*
* Wakeon lan
*
*/
#define WOL_MSG_LEN (6 + 16*6)
extern int wakeup_server(char *);
#endif /* _USR_WOL_H */