summaryrefslogtreecommitdiffstats
path: root/src/arch/i386/image/comboot.c
diff options
context:
space:
mode:
authorMichael Brown2009-02-17 01:47:35 +0100
committerMichael Brown2009-02-17 01:47:35 +0100
commit8904cd55f128941d53d9a8beef71fb32a920a92d (patch)
treea2ce11209520f09931d23ccae2682297ada99288 /src/arch/i386/image/comboot.c
parent[uri] Allow use of relative URIs when calling churi() (diff)
downloadipxe-8904cd55f128941d53d9a8beef71fb32a920a92d.tar.gz
ipxe-8904cd55f128941d53d9a8beef71fb32a920a92d.tar.xz
ipxe-8904cd55f128941d53d9a8beef71fb32a920a92d.zip
[comboot] Allow for tail recursion of COMBOOT images
Multi-level menus via COMBOOT rely on the COMBOOT program being able to exit and invoke a new COMBOOT program (the next menu). This works, but rapidly (within about five iterations) runs out of space in gPXE's internal stack, since each new image is executed in a new function context. Fix by allowing tail recursion between images; an image can now specify a replacement image for itself, and image_exec() will perform the necessary tail recursion.
Diffstat (limited to 'src/arch/i386/image/comboot.c')
-rw-r--r--src/arch/i386/image/comboot.c40
1 files changed, 23 insertions, 17 deletions
diff --git a/src/arch/i386/image/comboot.c b/src/arch/i386/image/comboot.c
index 63d02c0fe..3ca9d28f4 100644
--- a/src/arch/i386/image/comboot.c
+++ b/src/arch/i386/image/comboot.c
@@ -142,16 +142,16 @@ static int comboot_exec ( struct image *image ) {
comboot_init_psp ( image, seg_userptr );
/* Hook COMBOOT API interrupts */
- hook_comboot_interrupts ( );
+ hook_comboot_interrupts();
DBGC ( image, "executing 16-bit COMBOOT image at %4x:0100\n",
- COMBOOT_PSP_SEG );
+ COMBOOT_PSP_SEG );
- /* Temporarily de-register image, so that a "boot" command
- * doesn't throw us into an execution loop. Hold a reference
- * to avoid the image's being freed.
+ /* Unregister image, so that a "boot" command doesn't
+ * throw us into an execution loop. We never
+ * reregister ourselves; COMBOOT images expect to be
+ * removed on exit.
*/
- image_get ( image );
unregister_image ( image );
/* Store stack segment at 0x38 and stack pointer at 0x3A
@@ -180,26 +180,32 @@ static int comboot_exec ( struct image *image ) {
"xorw %%bp, %%bp\n\t"
"lret\n\t" )
: : "r" ( COMBOOT_PSP_SEG ) : "eax" );
+ DBGC ( image, "COMBOOT %p: returned\n", image );
break;
- case COMBOOT_RETURN_RUN_KERNEL:
- DBGC ( image, "COMBOOT %p: returned to run kernel...\n", image );
- comboot_run_kernel ( );
+ case COMBOOT_EXIT:
+ DBGC ( image, "COMBOOT %p: exited\n", image );
break;
- case COMBOOT_RETURN_EXIT:
+ case COMBOOT_EXIT_RUN_KERNEL:
+ DBGC ( image, "COMBOOT %p: exited to run kernel %p\n",
+ image, comboot_replacement_image );
+ image->replacement = comboot_replacement_image;
+ image_autoload ( image->replacement );
break;
- }
+ case COMBOOT_EXIT_COMMAND:
+ DBGC ( image, "COMBOOT %p: exited after executing command\n",
+ image );
+ break;
- comboot_force_text_mode ( );
+ default:
+ assert ( 0 );
+ break;
+ }
- DBGC ( image, "COMBOOT %p returned\n", image );
+ comboot_force_text_mode();
- /* Re-register image and return */
- register_image ( image );
- image_put ( image );
-
return 0;
}