20#include "pedigree/kernel/Log.h"
21#include "pedigree/kernel/Subsystem.h"
22#include "pedigree/kernel/compiler.h"
23#include "pedigree/kernel/core/BootIO.h"
24#include "pedigree/kernel/process/Process.h"
25#include "pedigree/kernel/process/Thread.h"
26#include "pedigree/kernel/processor/Processor.h"
27#include "pedigree/kernel/processor/ProcessorInformation.h"
29#include "modules/Module.h"
30#include "modules/subsys/posix/FileDescriptor.h"
31#include "modules/subsys/posix/PosixProcess.h"
32#include "modules/subsys/posix/PosixSubsystem.h"
33#include "modules/subsys/posix/ResolvedPath.h"
34#include "modules/system/vfs/MountView.h"
35#include "modules/system/vfs/VFS.h"
37#include "pedigree/kernel/processor/hosted/smoke.h"
39#include "pedigree/kernel/utilities/StaticString.h"
40#include "pedigree/kernel/utilities/String.h"
41#include "pedigree/kernel/utilities/Vector.h"
42#include "pedigree/kernel/utilities/new"
48static Thread* g_pStage2Thread = 0;
50static void error(
const char* s) {
55 bootIO.
write(str, BootIO::Red, BootIO::Black);
67 result.retain(selected);
71static int init_stage2(
void* param) {
73 if (!HOSTED_SMOKE_TESTS) {
74 extern void system_reset();
75 NOTICE(
"Hosted build has no smoke-test command; shutting down.");
81 if (g_HostedSmokeStage == HostedSmokeRoot) {
82 extern void system_reset();
83 NOTICE(
"HOSTED-SMOKE: root mounted");
90 bool tryingLinux =
false;
91 bool directHostedSmokeCommand =
false;
98 directHostedSmokeCommand = HOSTED_SMOKE_TESTS && ((g_HostedSmokeStage == HostedSmokeCommand) ||
99 (g_HostedSmokeStage == HostedSmokeShutdown));
101 init_path.assign(directHostedSmokeCommand ?
"/usr/bin/hosted-smoke-command" :
"/usr/bin/init");
102 NOTICE(
"Searching for userspace program at " << init_path);
103 file = resolveBootPath(init_path, executable);
104 if (!file && !directHostedSmokeCommand) {
105 WARNING(
"Did not find " << init_path <<
", trying for a Linux userspace...");
106 init_path.assign(
"/sbin/init");
109 NOTICE(
"Searching for Linux init at " << init_path);
110 file = resolveBootPath(init_path, executable);
114 error(directHostedSmokeCommand
115 ?
"failed to find hosted smoke command"
116 :
"failed to find init program (tried /usr/bin/init and /sbin/init)");
120 NOTICE(
"Found a userspace program at " << init_path);
126 if (!tryingLinux && HOSTED_SMOKE_TESTS) {
127 switch (g_HostedSmokeStage) {
128 case HostedSmokeInit:
131 case HostedSmokeCommand:
134 case HostedSmokeShutdown:
151 NOTICE(
"Invoking userspace program at " << init_path);
152 if (!pProcess->getSubsystem()->
invoke(init_path.cstr(), argv, env)) {
153 error(
"failed to load userspace program");
162 if (!HOSTED_SMOKE_TESTS) {
163 extern void system_reset();
164 NOTICE(
"Hosted build has no smoke-test command; shutting down.");
178 if (!view || !context ||
180 error(
"/dev/null does not exist");
184 nullPath.retain(selectedNull);
190 if (!pProcess || !pProcess->jobControlReady() || !pProcess->filesystemContextReady()) {
192 error(
"Unable to initialise the process session");
197 if (!pProcess->installUserIdentity(bootstrap->
getUser(), bootstrap->
getGroup(),
nullptr, 0)) {
199 error(
"Unable to initialise the process identity");
209 error(
"Unable to initialise the process subsystem");
212 pProcess->setSubsystem(pSubsystem);
222 if (pSubsystem->traceContext().prepareTask(preparedTrace) != TraceStatus::Success) {
224 error(
"Unable to initialise the process task identity");
229 if (!pSubsystem->namespaceContext() || !pSubsystem->namespaceContext()->valid() ||
230 posix_uts_initial(initialUts) != UtsStatus::Success ||
231 posix_uts_prepare_thread(initialUts,
false, preparedUts) != UtsStatus::Success) {
233 error(
"Unable to initialise the process namespace");
237 g_pStage2Thread =
new Thread(pProcess, init_stage2, 0, 0,
false,
false,
true);
238 if (!g_pStage2Thread) {
240 error(
"Unable to initialise the process thread");
243 pSubsystem->namespaceContext()->publishThread(preparedUts, *g_pStage2Thread,
true);
244 if (pSubsystem->traceContext().publishTask(preparedTrace, *g_pStage2Thread) !=
245 TraceStatus::Success)
246 FATAL(
"Initial trace task publication failed");
247 g_pStage2Thread->setName(
"init");
249 if (!g_pStage2Thread->
start()) {
250 FATAL(
"init: delayed initial thread could not be started.");
254 g_pStage2Thread->
join();
260static void destroy() {}
263#define __MOD_DEPS "vfs", "posix", "linker", "users"
264#define __MOD_DEPS_OPT "gfx-deps", "mountroot", "confignics"
266#define __MOD_DEPS "vfs", "posix", "linker", "users"
267#define __MOD_DEPS_OPT "mountroot", "confignics"
269MODULE_INFO(
"init", &init, &destroy, __MOD_DEPS);
271MODULE_OPTIONAL_DEPENDS(__MOD_DEPS_OPT);
EXPORTED_PUBLIC void write(T &str, Colour foreColour, Colour backColour)
void addFileDescriptor(size_t fd, FileDescriptor *pFd)
LargeStaticString & description()
static void setInit(Process *pProcess)
static ProcessorInformation & information()
virtual bool invoke(const char *name, Vector< String > &argv, Vector< String > &env)=0
A vector / dynamic array.
void pushBack(const T &value)