2 * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA
20 FILE_LICENCE ( GPL2_OR_LATER
);
23 #include <ipxe/efi/efi_driver.h>
24 #include <ipxe/efi/efi_snp.h>
25 #include <ipxe/efi/efi_strings.h>
26 #include <ipxe/umalloc.h>
28 #include <ipxe/init.h>
29 #include <usr/ifmgmt.h>
30 #include <usr/route.h>
31 #include <usr/autoboot.h>
33 #define MAX_EXIT_BUFFER_SIZE 256
36 * Close all open net devices
38 * Called before a fresh boot attempt in order to free up memory. We
39 * don't just close the device immediately after the boot fails,
40 * because there may still be TCP connections in the process of
43 static void close_all_netdevs ( void ) {
44 struct net_device
*netdev
;
46 for_each_netdev ( netdev
) {
51 static struct uri
* try_getting_next_server ( struct net_device
*netdev
) {
54 /* Close all other network devices */
57 /* Open device and display device status */
58 if ( ifopen ( netdev
) != 0 )
62 /* Configure device */
63 if (ifconf ( netdev
, NULL
)!= 0 )
67 /* Fetch next server and filename */
68 filename
= fetch_next_server_and_filename ( NULL
);
71 if ( ! uri_has_path ( filename
) ) {
72 /* Ignore empty filename */
85 static struct uri
* efi_discover ( void ) {
86 struct net_device
*netdev
;
88 struct uri
* filename
= NULL
;
90 for_each_netdev ( netdev
) {
91 filename
= try_getting_next_server ( netdev
);
100 * @v image_handle Image handle
101 * @v systab System table
102 * @ret efirc EFI return status code
104 EFI_STATUS EFIAPI
_efi_discovery_start ( EFI_HANDLE image_handle
,
105 EFI_SYSTEM_TABLE
*systab
) {
107 struct uri
* filename
;
111 /* Initialise EFI environment */
112 if ( ( efirc
= efi_init ( image_handle
, systab
) ) != 0 )
115 if ( ( user_buf
= umalloc(MAX_EXIT_BUFFER_SIZE
*2) ) == 0)
117 efirc
= EFI_OUT_OF_RESOURCES
;
121 exit_buf
= (wchar_t *)user_to_phys(user_buf
,0);
126 if ( ( filename
= efi_discover() ) == NULL
)
128 efirc
= EFI_NOT_FOUND
;
133 efi_loaded_image
->Unload ( image_handle
);
134 efi_driver_reconnect_all();
136 efi_snprintf(exit_buf
,MAX_EXIT_BUFFER_SIZE
,"%s - %s", filename
->host
, filename
->path
);
139 systab
->BootServices
->Exit(image_handle
, efirc
, MAX_EXIT_BUFFER_SIZE
, (CHAR16
*) exit_buf
);
143 systab
->BootServices
->Exit(image_handle
, efirc
, 0, NULL
);
150 * @v rootdev EFI root device
152 static int efi_probe ( struct root_device
*rootdev __unused
) {
154 return efi_driver_connect_all();
158 * Remove EFI root bus
160 * @v rootdev EFI root device
162 static void efi_remove ( struct root_device
*rootdev __unused
) {
164 efi_driver_disconnect_all();
167 /** EFI root device driver */
168 static struct root_driver efi_root_driver
= {
170 .remove
= efi_remove
,
173 /** EFI root device */
174 struct root_device efi_root_device __root_device
= {
175 .dev
= { .name
= "EFI" },
176 .driver
= &efi_root_driver
,