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