Add extra environment config.
[SquirrelJME.git] / nanocoat / src / boot.c
blob8083a391c4a809acd19427437bb73651003f5a70
1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // SquirrelJME
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 // -------------------------------------------------------------------------*/
10 #include <string.h>
12 #include "sjme/allocSizeOf.h"
13 #include "sjme/boot.h"
14 #include "sjme/debug.h"
15 #include "sjme/except.h"
16 #include "sjme/nvm.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)
23 sjme_errorCode error;
24 void* reservedBase;
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... */
32 reservedBase = NULL;
33 reservedSize = -1;
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. */
43 reservedPool = NULL;
44 if (sjme_error_is(error = sjme_alloc_poolInitStatic(
45 &reservedPool, reservedBase, reservedSize)) ||
46 reservedPool == NULL)
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
59 sjme_errorCode error;
60 sjme_exceptTrace* trace;
61 sjme_jint i, n;
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,
76 &reservedPool)))
77 goto fail_reservedPoolAlloc;
79 /* Allocate resultant state. */
80 result = NULL;
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)) ||
89 result == NULL)
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));
103 numMergeSuites = 0;
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)
116 numMergeSuites++;
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)
126 goto fail_noSuites;
128 /* Use the single suite only. */
129 else if (numMergeSuites == 1)
130 result->suite = mergeSuites[0];
132 /* Merge everything into one. */
133 else
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. */
143 classPath = NULL;
144 error = SJME_ERROR_UNKNOWN;
145 if (result->bootParamCopy->mainClassPathById != NULL)
146 error = sjme_rom_resolveClassPathById(result->suite,
147 result->bootParamCopy->mainClassPathById,
148 &classPath);
149 else
150 error = sjme_rom_resolveClassPathByName(result->suite,
151 result->bootParamCopy->mainClassPathByName,
152 &classPath);
154 /* Failed to resolve? */
155 if (sjme_error_is(error) || classPath == NULL)
157 /* Debug. */
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. */
172 initTask = NULL;
173 if (sjme_error_is(error = sjme_task_start(result,
174 &initTaskConfig, &initTask)) || initTask == NULL)
175 goto fail_initTask;
177 /* Return newly created VM. */
178 *outState = result;
179 return SJME_ERROR_NONE;
181 /* Failed at specific points... */
182 fail_initTask:
183 fail_badClassPath:
184 fail_suiteMerge:
185 fail_noSuites:
186 fail_payloadRom:
187 fail_bothIdAndName:
188 fail_bootParamCopy:
189 if (result != NULL && result->bootParamCopy != NULL)
190 sjme_alloc_free(result->bootParamCopy);
192 fail_resultAlloc:
193 if (result != NULL)
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)
204 if (state == NULL)
205 return SJME_ERROR_NULL_ARGUMENTS;
207 /* Free sub-structures. */
208 if (SJME_JNI_TRUE)
209 sjme_todo("sjme_nvm_destroy()");
211 /* Free main structure. */
212 if (SJME_JNI_TRUE)
213 sjme_todo("sjme_nvm_destroy()");
215 /* Set exit code, if requested. */
216 if (SJME_JNI_TRUE)
217 sjme_todo("sjme_nvm_destroy()");
219 /* Finished. */
220 sjme_todo("sjme_nvm_destroy()");
221 return SJME_ERROR_NOT_IMPLEMENTED;