1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // -------------------------------------------------------------------------*/
12 #include "sjme/allocSizeOf.h"
13 #include "sjme/boot.h"
14 #include "sjme/debug.h"
15 #include "sjme/except.h"
17 #include "sjme/task.h"
19 sjme_errorCode
sjme_nvm_allocReservedPool(
20 sjme_attrInNotNull sjme_alloc_pool
* mainPool
,
21 sjme_attrOutNotNull sjme_alloc_pool
** outReservedPool
)
25 sjme_alloc_pool
* reservedPool
;
26 sjme_jint reservedSize
;
28 if (mainPool
== NULL
|| outReservedPool
== NULL
)
29 return SJME_ERROR_NULL_ARGUMENTS
;
31 /* Determine how big the reserved pool should be... */
34 if (sjme_error_is(error
= sjme_alloc_sizeOf(
35 SJME_ALLOC_SIZEOF_RESERVED_POOL
, 0, &reservedSize
)))
36 return sjme_error_default(error
);
37 if (sjme_error_is(error
= sjme_alloc(mainPool
,
38 reservedSize
, (void**)&reservedBase
) ||
39 reservedBase
== NULL
))
40 return sjme_error_default(error
);
42 /* Initialize a reserved pool where all of our own data structures go. */
44 if (sjme_error_is(error
= sjme_alloc_poolInitStatic(
45 &reservedPool
, reservedBase
, reservedSize
)) ||
47 return sjme_error_default(error
);
49 /* Use the resultant pool. */
50 *outReservedPool
= reservedPool
;
51 return SJME_ERROR_NONE
;
54 sjme_errorCode
sjme_nvm_boot(sjme_alloc_pool
* mainPool
,
55 sjme_alloc_pool
* reservedPool
, const sjme_nvm_bootParam
* param
,
56 sjme_nvm_state
** outState
)
58 #define FIXED_SUITE_COUNT 16
60 sjme_exceptTrace
* trace
;
62 sjme_nvm_state
* result
;
63 sjme_rom_suite mergeSuites
[FIXED_SUITE_COUNT
];
64 sjme_jint numMergeSuites
;
65 sjme_task_startConfig initTaskConfig
;
66 sjme_nvm_task initTask
;
67 sjme_list_sjme_rom_library
* classPath
;
69 if (param
== NULL
|| outState
== NULL
)
70 return SJME_ERROR_NULL_ARGUMENTS
;
72 /* Set up a reserved pool where all the data structures for the VM go... */
73 /* But only if one does not exist. */
74 if (reservedPool
== NULL
)
75 if (sjme_error_is(error
= sjme_nvm_allocReservedPool(mainPool
,
77 goto fail_reservedPoolAlloc
;
79 /* Allocate resultant state. */
81 if (sjme_error_is(error
= sjme_alloc(reservedPool
,
82 sizeof(*result
), (void**)&result
)) || result
== NULL
)
83 goto fail_resultAlloc
;
85 /* Make a defensive copy of the boot parameters. */
86 if (sjme_error_is(error
= sjme_alloc_copy(reservedPool
,
87 sizeof(sjme_nvm_bootParam
),
88 (void**)&result
->bootParamCopy
, param
)) ||
90 goto fail_bootParamCopy
;
92 /* Can only use one or the other to get the class path. */
93 if (result
->bootParamCopy
->mainClassPathById
!= NULL
&&
94 result
->bootParamCopy
->mainClassPathByName
!= NULL
)
95 goto fail_bothIdAndName
;
97 /* Set parameters accordingly. */
98 result
->allocPool
= mainPool
;
99 result
->reservedPool
= reservedPool
;
101 /* Initialize base for suite merging. */
102 memset(mergeSuites
, 0, sizeof(mergeSuites
));
105 /* Process payload suites. */
106 if (result
->bootParamCopy
->payload
!= NULL
)
108 /* Scan accordingly. */
109 if (sjme_error_is(error
= sjme_rom_suiteFromPayload(reservedPool
,
110 &mergeSuites
[numMergeSuites
],
111 result
->bootParamCopy
->payload
)))
112 goto fail_payloadRom
;
114 /* Was a suite generated? */
115 if (mergeSuites
[numMergeSuites
] != NULL
)
119 /* Is there a pre-existing suite to use? */
120 if (result
->bootParamCopy
->suite
!= NULL
)
121 mergeSuites
[numMergeSuites
++] =
122 (sjme_rom_suite
)result
->bootParamCopy
->suite
;
124 /* No suites at all? Running with absolutely nothing??? */
125 if (numMergeSuites
<= 0)
128 /* Use the single suite only. */
129 else if (numMergeSuites
== 1)
130 result
->suite
= mergeSuites
[0];
132 /* Merge everything into one. */
135 /* Merge all the suites together into one. */
136 if (sjme_error_is(error
= sjme_rom_suiteFromMerge(reservedPool
,
137 &result
->suite
, mergeSuites
,
138 numMergeSuites
)) || result
->suite
== NULL
)
139 goto fail_suiteMerge
;
142 /* Resolve class path libraries. */
144 error
= SJME_ERROR_UNKNOWN
;
145 if (result
->bootParamCopy
->mainClassPathById
!= NULL
)
146 error
= sjme_rom_resolveClassPathById(result
->suite
,
147 result
->bootParamCopy
->mainClassPathById
,
150 error
= sjme_rom_resolveClassPathByName(result
->suite
,
151 result
->bootParamCopy
->mainClassPathByName
,
154 /* Failed to resolve? */
155 if (sjme_error_is(error
) || classPath
== NULL
)
158 sjme_message("Classpath resolve failure: %d %p", error
, classPath
);
160 goto fail_badClassPath
;
163 /* Setup task details. */
164 initTaskConfig
.stdOut
= SJME_TASK_PIPE_REDIRECT_TYPE_TERMINAL
;
165 initTaskConfig
.stdErr
= SJME_TASK_PIPE_REDIRECT_TYPE_TERMINAL
;
166 initTaskConfig
.classPath
= classPath
;
167 initTaskConfig
.mainClass
= result
->bootParamCopy
->mainClass
;
168 initTaskConfig
.mainArgs
= result
->bootParamCopy
->mainArgs
;
169 initTaskConfig
.sysProps
= result
->bootParamCopy
->sysProps
;
171 /* Spawn initial task which uses the main arguments. */
173 if (sjme_error_is(error
= sjme_task_start(result
,
174 &initTaskConfig
, &initTask
)) || initTask
== NULL
)
177 /* Return newly created VM. */
179 return SJME_ERROR_NONE
;
181 /* Failed at specific points... */
189 if (result
!= NULL
&& result
->bootParamCopy
!= NULL
)
190 sjme_alloc_free(result
->bootParamCopy
);
194 sjme_alloc_free(result
);
196 fail_reservedPoolAlloc
:
198 /* Use whatever error code. */
199 return sjme_error_defaultOr(error
, SJME_ERROR_BOOT_FAILURE
);
202 sjme_errorCode
sjme_nvm_destroy(sjme_nvm_state
* state
, sjme_jint
* exitCode
)
205 return SJME_ERROR_NULL_ARGUMENTS
;
207 /* Free sub-structures. */
209 sjme_todo("sjme_nvm_destroy()");
211 /* Free main structure. */
213 sjme_todo("sjme_nvm_destroy()");
215 /* Set exit code, if requested. */
217 sjme_todo("sjme_nvm_destroy()");
220 sjme_todo("sjme_nvm_destroy()");
221 return SJME_ERROR_NOT_IMPLEMENTED
;