#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <byteswap.h>
#include <curses.h>
#include <console.h>
#include <gpxe/dhcp.h>
#include <gpxe/keys.h>
#include <gpxe/timer.h>
#include <gpxe/process.h>
#include <usr/dhcpmgmt.h>
#include <usr/autoboot.h>
Go to the source code of this file.
Data Structures | |
| struct | pxe_menu_item |
| A PXE boot menu item. More... | |
| struct | pxe_menu |
| A PXE boot menu. More... | |
Defines | |
| #define | CPAIR_NORMAL 1 |
| #define | CPAIR_SELECT 2 |
Functions | |
| FILE_LICENCE (GPL2_OR_LATER) | |
| static int | pxe_menu_parse (struct pxe_menu **menu) |
| Parse and allocate PXE boot menu. | |
| static void | pxe_menu_draw_item (struct pxe_menu *menu, unsigned int index, int selected) |
| Draw PXE boot menu item. | |
| static int | pxe_menu_select (struct pxe_menu *menu) |
| Make selection from PXE boot menu. | |
| static int | pxe_menu_prompt_and_select (struct pxe_menu *menu) |
| Prompt for (and make selection from) PXE boot menu. | |
| int | pxe_menu_boot (struct net_device *netdev) |
| Boot using PXE boot menu. | |
Definition in file pxemenu.c.
| FILE_LICENCE | ( | GPL2_OR_LATER | ) |
| static int pxe_menu_parse | ( | struct pxe_menu ** | menu | ) | [static] |
Parse and allocate PXE boot menu.
| menu | PXE boot menu to fill in |
| rc | Return status code |
Definition at line 86 of file pxemenu.c.
References DBG, dhcp_pxe_boot_menu::desc, dhcp_pxe_boot_menu::desc_len, DHCP_PXE_BOOT_MENU, DHCP_PXE_BOOT_MENU_PROMPT, ENOMEM, ENOSPC, fetch_setting(), fetch_setting_len(), le16_to_cpu, memcpy, memset(), NULL, dhcp_pxe_boot_menu_prompt::prompt, strerror(), setting::tag, dhcp_pxe_boot_menu_prompt::timeout, dhcp_pxe_boot_menu::type, and zalloc().
Referenced by pxe_menu_boot().
00086 { 00087 struct setting pxe_boot_menu_prompt_setting = 00088 { .tag = DHCP_PXE_BOOT_MENU_PROMPT }; 00089 struct setting pxe_boot_menu_setting = 00090 { .tag = DHCP_PXE_BOOT_MENU }; 00091 uint8_t raw_menu[256]; 00092 int raw_prompt_len; 00093 int raw_menu_len; 00094 struct dhcp_pxe_boot_menu *raw_menu_item; 00095 struct dhcp_pxe_boot_menu_prompt *raw_menu_prompt; 00096 void *raw_menu_end; 00097 unsigned int num_menu_items; 00098 unsigned int i; 00099 int rc; 00100 00101 /* Fetch raw menu */ 00102 memset ( raw_menu, 0, sizeof ( raw_menu ) ); 00103 if ( ( raw_menu_len = fetch_setting ( NULL, &pxe_boot_menu_setting, 00104 raw_menu, 00105 sizeof ( raw_menu ) ) ) < 0 ) { 00106 rc = raw_menu_len; 00107 DBG ( "Could not retrieve raw PXE boot menu: %s\n", 00108 strerror ( rc ) ); 00109 return rc; 00110 } 00111 if ( raw_menu_len >= ( int ) sizeof ( raw_menu ) ) { 00112 DBG ( "Raw PXE boot menu too large for buffer\n" ); 00113 return -ENOSPC; 00114 } 00115 raw_menu_end = ( raw_menu + raw_menu_len ); 00116 00117 /* Fetch raw prompt length */ 00118 raw_prompt_len = fetch_setting_len ( NULL, 00119 &pxe_boot_menu_prompt_setting ); 00120 if ( raw_prompt_len < 0 ) 00121 raw_prompt_len = 0; 00122 00123 /* Count menu items */ 00124 num_menu_items = 0; 00125 raw_menu_item = ( ( void * ) raw_menu ); 00126 while ( 1 ) { 00127 if ( ( ( ( void * ) raw_menu_item ) + 00128 sizeof ( *raw_menu_item ) ) > raw_menu_end ) 00129 break; 00130 if ( ( ( ( void * ) raw_menu_item ) + 00131 sizeof ( *raw_menu_item ) + 00132 raw_menu_item->desc_len ) > raw_menu_end ) 00133 break; 00134 num_menu_items++; 00135 raw_menu_item = ( ( ( void * ) raw_menu_item ) + 00136 sizeof ( *raw_menu_item ) + 00137 raw_menu_item->desc_len ); 00138 } 00139 00140 /* Allocate space for parsed menu */ 00141 *menu = zalloc ( sizeof ( **menu ) + 00142 ( num_menu_items * sizeof ( (*menu)->items[0] ) ) + 00143 raw_menu_len + 1 /* NUL */ + 00144 raw_prompt_len + 1 /* NUL */ ); 00145 if ( ! *menu ) { 00146 DBG ( "Could not allocate PXE boot menu\n" ); 00147 return -ENOMEM; 00148 } 00149 00150 /* Fill in parsed menu */ 00151 (*menu)->num_items = num_menu_items; 00152 raw_menu_item = ( ( ( void * ) (*menu) ) + sizeof ( **menu ) + 00153 ( num_menu_items * sizeof ( (*menu)->items[0] ) ) ); 00154 memcpy ( raw_menu_item, raw_menu, raw_menu_len ); 00155 for ( i = 0 ; i < num_menu_items ; i++ ) { 00156 (*menu)->items[i].type = le16_to_cpu ( raw_menu_item->type ); 00157 (*menu)->items[i].desc = raw_menu_item->desc; 00158 /* Set type to 0; this ensures that the description 00159 * for the previous menu item is NUL-terminated. 00160 * (Final item is NUL-terminated anyway.) 00161 */ 00162 raw_menu_item->type = 0; 00163 raw_menu_item = ( ( ( void * ) raw_menu_item ) + 00164 sizeof ( *raw_menu_item ) + 00165 raw_menu_item->desc_len ); 00166 } 00167 if ( raw_prompt_len ) { 00168 raw_menu_prompt = ( ( ( void * ) raw_menu_item ) + 00169 1 /* NUL */ ); 00170 fetch_setting ( NULL, &pxe_boot_menu_prompt_setting, 00171 raw_menu_prompt, raw_prompt_len ); 00172 (*menu)->timeout = 00173 ( ( raw_menu_prompt->timeout == 0xff ) ? 00174 -1 : raw_menu_prompt->timeout ); 00175 (*menu)->prompt = raw_menu_prompt->prompt; 00176 } else { 00177 (*menu)->timeout = -1; 00178 } 00179 00180 return 0; 00181 }
| static void pxe_menu_draw_item | ( | struct pxe_menu * | menu, | |
| unsigned int | index, | |||
| int | selected | |||
| ) | [static] |
Draw PXE boot menu item.
| menu | PXE boot menu | |
| index | Index of item to draw | |
| selected | Item is selected |
Definition at line 190 of file pxemenu.c.
References color_set, COLS, CPAIR_NORMAL, CPAIR_SELECT, pxe_menu_item::desc, pxe_menu::items, LINES, move(), mvprintw, NULL, pxe_menu::num_items, and snprintf().
Referenced by pxe_menu_select().
00191 { 00192 char buf[COLS+1]; 00193 size_t len; 00194 unsigned int row; 00195 00196 /* Prepare space-padded row content */ 00197 len = snprintf ( buf, sizeof ( buf ), " %c. %s", 00198 ( 'A' + index ), menu->items[index].desc ); 00199 while ( len < ( sizeof ( buf ) - 1 ) ) 00200 buf[len++] = ' '; 00201 buf[ sizeof ( buf ) - 1 ] = '\0'; 00202 00203 /* Draw row */ 00204 row = ( LINES - menu->num_items + index ); 00205 color_set ( ( selected ? CPAIR_SELECT : CPAIR_NORMAL ), NULL ); 00206 mvprintw ( row, 0, "%s", buf ); 00207 move ( row, 1 ); 00208 }
| static int pxe_menu_select | ( | struct pxe_menu * | menu | ) | [static] |
Make selection from PXE boot menu.
| menu | PXE boot menu |
| rc | Return status code |
Definition at line 216 of file pxemenu.c.
References COLOR_BLACK, color_set, COLOR_WHITE, CPAIR_NORMAL, CPAIR_SELECT, CR, CTRL_C, ECANCELED, endwin(), ESC, getkey(), init_pair(), initscr(), iskey(), KEY_DOWN, KEY_MIN, KEY_UP, LF, NULL, pxe_menu::num_items, printf(), pxe_menu_draw_item(), pxe_menu::selection, start_color, step(), and toupper().
Referenced by pxe_menu_prompt_and_select().
00216 { 00217 int key; 00218 unsigned int key_selection; 00219 unsigned int i; 00220 int rc = 0; 00221 00222 /* Initialise UI */ 00223 initscr(); 00224 start_color(); 00225 init_pair ( CPAIR_NORMAL, COLOR_WHITE, COLOR_BLACK ); 00226 init_pair ( CPAIR_SELECT, COLOR_BLACK, COLOR_WHITE ); 00227 color_set ( CPAIR_NORMAL, NULL ); 00228 00229 /* Draw initial menu */ 00230 for ( i = 0 ; i < menu->num_items ; i++ ) 00231 printf ( "\n" ); 00232 for ( i = 0 ; i < menu->num_items ; i++ ) 00233 pxe_menu_draw_item ( menu, ( menu->num_items - i - 1 ), 0 ); 00234 00235 while ( 1 ) { 00236 00237 /* Highlight currently selected item */ 00238 pxe_menu_draw_item ( menu, menu->selection, 1 ); 00239 00240 /* Wait for keyboard input */ 00241 while ( ! iskey() ) 00242 step(); 00243 key = getkey(); 00244 00245 /* Unhighlight currently selected item */ 00246 pxe_menu_draw_item ( menu, menu->selection, 0 ); 00247 00248 /* Act upon key */ 00249 if ( ( key == CR ) || ( key == LF ) ) { 00250 pxe_menu_draw_item ( menu, menu->selection, 1 ); 00251 break; 00252 } else if ( ( key == CTRL_C ) || ( key == ESC ) ) { 00253 rc = -ECANCELED; 00254 break; 00255 } else if ( key == KEY_UP ) { 00256 if ( menu->selection > 0 ) 00257 menu->selection--; 00258 } else if ( key == KEY_DOWN ) { 00259 if ( menu->selection < ( menu->num_items - 1 ) ) 00260 menu->selection++; 00261 } else if ( ( key < KEY_MIN ) && 00262 ( ( key_selection = ( toupper ( key ) - 'A' ) ) 00263 < menu->num_items ) ) { 00264 menu->selection = key_selection; 00265 pxe_menu_draw_item ( menu, menu->selection, 1 ); 00266 break; 00267 } 00268 } 00269 00270 /* Shut down UI */ 00271 endwin(); 00272 00273 return rc; 00274 }
| static int pxe_menu_prompt_and_select | ( | struct pxe_menu * | menu | ) | [static] |
Prompt for (and make selection from) PXE boot menu.
| menu | PXE boot menu |
| rc | Return status code |
Definition at line 282 of file pxemenu.c.
References CTRL_C, currticks(), ECANCELED, ESC, getkey(), iskey(), KEY_F8, printf(), pxe_menu::prompt, pxe_menu_select(), TICKS_PER_SEC, and pxe_menu::timeout.
Referenced by pxe_menu_boot().
00282 { 00283 unsigned long start = currticks(); 00284 unsigned long now; 00285 unsigned long elapsed; 00286 size_t len = 0; 00287 int key; 00288 int rc = 0; 00289 00290 /* Display menu immediately, if specified to do so */ 00291 if ( menu->timeout < 0 ) { 00292 if ( menu->prompt ) 00293 printf ( "%s\n", menu->prompt ); 00294 return pxe_menu_select ( menu ); 00295 } 00296 00297 /* Display prompt, if specified */ 00298 if ( menu->prompt ) 00299 printf ( "%s", menu->prompt ); 00300 00301 /* Wait for timeout, if specified */ 00302 while ( menu->timeout > 0 ) { 00303 if ( ! len ) 00304 len = printf ( " (%d)", menu->timeout ); 00305 if ( iskey() ) { 00306 key = getkey(); 00307 if ( key == KEY_F8 ) { 00308 /* Display menu */ 00309 printf ( "\n" ); 00310 return pxe_menu_select ( menu ); 00311 } else if ( ( key == CTRL_C ) || ( key == ESC ) ) { 00312 /* Abort */ 00313 rc = -ECANCELED; 00314 break; 00315 } else { 00316 /* Stop waiting */ 00317 break; 00318 } 00319 } 00320 now = currticks(); 00321 elapsed = ( now - start ); 00322 if ( elapsed >= TICKS_PER_SEC ) { 00323 menu->timeout -= 1; 00324 do { 00325 printf ( "\b \b" ); 00326 } while ( --len ); 00327 start = now; 00328 } 00329 } 00330 00331 /* Return with default option selected */ 00332 printf ( "\n" ); 00333 return rc; 00334 }
| int pxe_menu_boot | ( | struct net_device * | netdev | ) |
Boot using PXE boot menu.
| rc | Return status code |
Definition at line 345 of file pxemenu.c.
References assert, boot_next_server_and_filename(), fetch_ipv4_setting(), fetch_string_setting(), find_settings(), free(), pxe_menu::items, pxe_menu_parse(), pxe_menu_prompt_and_select(), pxebs(), PXEBS_SETTINGS_NAME, pxe_menu::selection, and pxe_menu_item::type.
Referenced by netboot().
00345 { 00346 struct pxe_menu *menu; 00347 unsigned int pxe_type; 00348 struct settings *pxebs_settings; 00349 struct in_addr next_server; 00350 char filename[256]; 00351 int rc; 00352 00353 /* Parse and allocate boot menu */ 00354 if ( ( rc = pxe_menu_parse ( &menu ) ) != 0 ) 00355 return rc; 00356 00357 /* Make selection from boot menu */ 00358 if ( ( rc = pxe_menu_prompt_and_select ( menu ) ) != 0 ) { 00359 free ( menu ); 00360 return rc; 00361 } 00362 pxe_type = menu->items[menu->selection].type; 00363 00364 /* Free boot menu */ 00365 free ( menu ); 00366 00367 /* Return immediately if local boot selected */ 00368 if ( ! pxe_type ) 00369 return 0; 00370 00371 /* Attempt PXE Boot Server Discovery */ 00372 if ( ( rc = pxebs ( netdev, pxe_type ) ) != 0 ) 00373 return rc; 00374 00375 /* Attempt boot */ 00376 pxebs_settings = find_settings ( PXEBS_SETTINGS_NAME ); 00377 assert ( pxebs_settings ); 00378 fetch_ipv4_setting ( pxebs_settings, &next_server_setting, 00379 &next_server ); 00380 fetch_string_setting ( pxebs_settings, &filename_setting, 00381 filename, sizeof ( filename ) ); 00382 return boot_next_server_and_filename ( next_server, filename ); 00383 }
1.5.7.1