~ubuntu-branches/ubuntu/gutsy/virtualbox-ose/gutsy

« back to all changes in this revision

Viewing changes to src/VBox/Devices/PC/Etherboot-src/arch/i386/core/callbacks.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2007-09-08 16:44:58 UTC
  • Revision ID: james.westby@ubuntu.com-20070908164458-wao29470vqtr8ksy
Tags: upstream-1.5.0-dfsg2
ImportĀ upstreamĀ versionĀ 1.5.0-dfsg2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Callout/callback interface for Etherboot
 
2
 *
 
3
 * This file provides the mechanisms for making calls from Etherboot
 
4
 * to external programs and vice-versa.
 
5
 *
 
6
 * Initial version by Michael Brown <mbrown@fensystems.co.uk>, January 2004.
 
7
 */
 
8
 
 
9
#include "etherboot.h"
 
10
#include "callbacks.h"
 
11
#include "realmode.h"
 
12
#include "segoff.h"
 
13
#include <stdarg.h>
 
14
 
 
15
/* Maximum amount of stack data that prefix may request to be passed
 
16
 * to its exit routine
 
17
 */
 
18
#define MAX_PREFIX_STACK_DATA 16
 
19
 
 
20
/* Prefix exit routine is defined in prefix object */
 
21
extern void prefix_exit ( void );
 
22
extern void prefix_exit_end ( void );
 
23
 
 
24
/*****************************************************************************
 
25
 *
 
26
 * IN_CALL INTERFACE
 
27
 *
 
28
 *****************************************************************************
 
29
 */
 
30
 
 
31
/* in_call(): entry point for calls in to Etherboot from external code. 
 
32
 *
 
33
 * Parameters: some set up by assembly code _in_call(), others as
 
34
 * passed from external code.
 
35
 */
 
36
uint32_t i386_in_call ( va_list ap, i386_pm_in_call_data_t pm_data,
 
37
                        uint32_t opcode ) {
 
38
        uint32_t ret;
 
39
        i386_rm_in_call_data_t rm_data;
 
40
        in_call_data_t in_call_data = { &pm_data, NULL };
 
41
        struct {
 
42
                int data[MAX_PREFIX_STACK_DATA/4];
 
43
        } in_stack;
 
44
 
 
45
        /* Fill out rm_data if we were called from real mode */
 
46
        if ( opcode & EB_CALL_FROM_REAL_MODE ) {
 
47
                in_call_data.rm = &rm_data;
 
48
                rm_data = va_arg ( ap, typeof(rm_data) );
 
49
                /* Null return address indicates to use the special
 
50
                 * prefix exit mechanism, and that there are
 
51
                 * parameters on the stack that the prefix wants
 
52
                 * handed to its exit routine.
 
53
                 */
 
54
                if ( rm_data.ret_addr.offset == 0 ) {
 
55
                        int n = va_arg ( ap, int ) / 4;
 
56
                        int i;
 
57
                        for ( i = 0; i < n; i++ ) {
 
58
                                in_stack.data[i] = va_arg ( ap, int );
 
59
                        }
 
60
                }
 
61
        }
 
62
        
 
63
        /* Hand off to main in_call() routine */
 
64
        ret = in_call ( &in_call_data, opcode, ap );
 
65
 
 
66
        /* If real-mode return address is null, it means that we
 
67
         * should exit via the prefix's exit path, which is part of
 
68
         * our image.  (This arrangement is necessary since the prefix
 
69
         * code itself may have been vapourised by the time we want to
 
70
         * return.)
 
71
         */
 
72
        if ( ( opcode & EB_CALL_FROM_REAL_MODE ) &&
 
73
             ( rm_data.ret_addr.offset == 0 ) ) {
 
74
                real_call ( prefix_exit, &in_stack, NULL );
 
75
                /* Should never return */
 
76
        }
 
77
                
 
78
        return ret;
 
79
}
 
80
 
 
81
#ifdef  CODE16
 
82
 
 
83
/* install_rm_callback_interface(): install real-mode callback
 
84
 * interface at specified address.
 
85
 *
 
86
 * Real-mode code may then call to this address (or lcall to this
 
87
 * address plus RM_IN_CALL_FAR) in order to make an in_call() to
 
88
 * Etherboot.
 
89
 *
 
90
 * Returns the size of the installed code, or 0 if the code could not
 
91
 * be installed.
 
92
 */
 
93
int install_rm_callback_interface ( void *address, size_t available ) {
 
94
        if ( available &&
 
95
             ( available < rm_callback_interface_size ) ) return 0;
 
96
 
 
97
        /* Inform RM code where to find Etherboot */
 
98
        rm_etherboot_location = virt_to_phys(_text);
 
99
 
 
100
        /* Install callback interface */
 
101
        memcpy ( address, &rm_callback_interface,
 
102
                 rm_callback_interface_size );
 
103
 
 
104
        return rm_callback_interface_size;
 
105
}
 
106
 
 
107
#endif  /* CODE16 */