[HOW-TO] Wake-on-Lan at preboot using Etherboot
#1
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
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 */
Reply

Logout Mark Read Team Forum Stats Members Help
[HOW-TO] Wake-on-Lan at preboot using Etherboot0