[Contribs] Add updated wake-on-LAN patch from Bill <level42@sympatico.ca>
[people/mcb30/gpxe.git] / contrib / wakeonlan / wol.c
1 /*
2  * Copyright (C) 2008 William Stewart.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 #include <stdio.h>
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <byteswap.h>
24 #include <gpxe/features.h>
25 #include <gpxe/netdevice.h>
26 #include <gpxe/if_ether.h>
27 #include <gpxe/iobuf.h>
28 #include <usr/ifmgmt.h>
29 #include <usr/wol.h>
30 #include <timer.h>
31
32 /** @file
33  *
34  * Wake on lan
35  *
36  */
37
38 /**
39  * Boot from a network device
40  *
41  * @v netdev            Network device
42  * @ret rc              Return status code
43  */
44 #define WOL_MSG_LEN (6 + 16*6)
45  
46 void wakeup_server(char *server_adr)
47 {
48         int rc, i,j;
49         unsigned char *buf;
50         uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
51         unsigned int len;
52         struct io_buffer *iobuf;
53         struct ethhdr *ethhdr;
54         struct net_device *netdev;
55         
56         for_each_netdev ( netdev ) {
57            break;
58         }
59
60         if (netdev == NULL)
61         {
62           printf("Could not find netdev\n");
63           return;
64         }
65                
66         /* Open device and display device status */
67         if ( (ifopen ( netdev ) ) != 0 )
68         {
69           printf("Could not open netdev\n");
70           return;
71         }
72
73         /* Create outgoing I/O buffer */
74         iobuf = alloc_iob ((ETH_HLEN + WOL_MSG_LEN)*2);
75         if (!iobuf)
76         {
77            printf("Could not allocate iob\n");
78            return;
79         }
80
81         ethhdr = iob_put(iobuf, sizeof(*ethhdr));
82         
83         /* Build Ethernet header */
84         memcpy (ethhdr->h_dest, eth_broadcast, ETH_ALEN );
85         memcpy (ethhdr->h_source, netdev->ll_addr, ETH_ALEN );
86         ethhdr->h_protocol = htons (0x0842);
87         
88         buf    = iob_put (iobuf, WOL_MSG_LEN);
89
90         /* Build the message to send - 6 x 0xff then 16 x dest address */
91         len =0;
92         for (i = 0; i < 6; i++)
93            buf[len++] = 0xff;
94         for (j = 0; j < 16; j++)
95            for (i = 0; i < 6; i++)
96                buf[len++] = server_adr[i];      
97
98         rc = netdev_tx (netdev, iobuf);
99
100         if (rc !=0)
101            printf("Failed to transmit WOL packet\n");
102
103         /* Give the controller a chance to send it before checking */
104         mdelay(100);
105
106         netdev_poll(netdev); 
107 }
108