1 using System;
2 using System.Collections;
3 using System.IO;
4 using cmsx.machine;
5 using cmsx.object;
6
7 namespace cmsx.kernel
8 {
9 public Section MakePoolSection(const List<string>& argv, const List<string>& environment, ulong& envDataAddress)
10 {
11 Section poolSection;
12 long n = argv.Count() + 1;
13 for (long i = 0; i < n; ++i;)
14 {
15 poolSection.EmitULong(0u);
16 }
17 long envBeginPos = poolSection.pos;
18 envDataAddress = poolSegmentBaseAddress + poolSection.Address();
19 long m = environment.Count() + 1;
20 for (long i = 0; i < m; ++i;)
21 {
22 poolSection.EmitULong(0u);
23 }
24 poolSection.Align(8u);
25 List<ulong> argAddresses;
26 for (const string& arg : argv)
27 {
28 argAddresses.Add(poolSegmentBaseAddress + poolSection.Address());
29 poolSection.EmitString(arg);
30 }
31 poolSection.Align(8u);
32 List<ulong> envAddresses;
33 for (const string& env : environment)
34 {
35 envAddresses.Add(poolSegmentBaseAddress + poolSection.Address());
36 poolSection.EmitString(env);
37 }
38 poolSection.pos = 0;
39 for (ulong argAddr : argAddresses)
40 {
41 poolSection.EmitULong(argAddr);
42 }
43 poolSection.pos = envBeginPos;
44 for (ulong envAddr : envAddresses)
45 {
46 poolSection.EmitULong(envAddr);
47 }
48 return poolSection;
49 }
50
51 public int Load(const string& programFileName, const List<string>& programArguments, int sid)
52 {
53 UniquePtr<BinaryFile> binaryFile = ReadBinaryFile(programFileName);
54 if (binaryFile.Get() is ExecutableFile*)
55 {
56 Machine& machine = GetMachine();
57 ProcessTable& processTable = GetProcessTable();
58 ExecutableFile* executable = cast<ExecutableFile*>(binaryFile.Get());
59 executable->AddSymbolsToAddressMap();
60 Section* codeSection = executable->GetCodeSection();
61 Section* dataSection = executable->GetDataSection();
62 Section* symbolSection = executable->GetSymbolSection();
63 string name = Path.GetFileName(programFileName);
64 List<string> argv;
65 argv.Add(name);
66 for (const string& arg : programArguments)
67 {
68 argv.Add(arg);
69 }
70 ulong envDataAddress = 0u;
71 Section poolSection = MakePoolSection(argv, List<string>(), envDataAddress);
72 long poolDataLength = Max(cast<long>(executable->InitialPoolSize()), poolSection.data.Count());
73 long poolSize = Align(poolDataLength, cast<long>(pageSize));
74 Symbol* mainFunctionSymbol = executable->GetSymbolTable().GetSymbol("Main");
75 Process* process = CreateSingleProcess(machine, processTable, name, mainFunctionSymbol->start, codeSection->BaseAddress(), codeSection->DataLength(), dataSection->DataLength(), cast<ulong>(poolSize),
76 cast<ulong>(executable->MinStackSize()), cast<ulong>(executable->MaxStackSize()), cast<ulong>(executable->StackSizeIncrement()), sid);
77 if (codeSection->DataLength() > 0u)
78 {
79 WriteProcessMemory(machine, process, codeSection->BaseAddress(), codeSection->data.Begin().Ptr(), cast<ulong>(codeSection->data.Count()), Protection.execute);
80 }
81 if (dataSection->DataLength() > 0u)
82 {
83 WriteProcessMemory(machine, process, dataSection->BaseAddress(), dataSection->data.Begin().Ptr(), cast<ulong>(dataSection->data.Count()), Protection.write);
84 }
85 if (!poolSection.data.IsEmpty())
86 {
87 WriteProcessMemory(machine, process, poolSegmentBaseAddress, poolSection.data.Begin().Ptr(), cast<ulong>(poolSection.data.Count()), Protection.write);
88 int ax = cast<int>(argv.Count());
89 ulong bx = poolSegmentBaseAddress;
90 WriteProcessMemory(machine, process, process->regAXAddress, cast<ulong>(ax), 8u, Protection.write);
91 WriteProcessMemory(machine, process, process->regBXAddress, bx, 8u, Protection.write);
92 WriteProcessMemory(machine, process, process->regCXAddress, 0u, 8u, Protection.write);
93 }
94 ulong poolStart = poolSegmentBaseAddress + cast<ulong>(poolSize);
95 ulong poolEnd = poolSegmentBaseAddress + cast<ulong>(poolSize);
96 process->poolStart = poolStart;
97 process->poolEnd = poolEnd;
98 Symbol* functionTableSymbol = executable->GetSymbolTable().GetSymbol("@function_table");
99 process->functionTableAddress = functionTableSymbol->start;
100 process->functionTableLength = functionTableSymbol->length;
101 executable = cast<ExecutableFile*>(binaryFile.Release());
102 Kernel& kernel = Kernel.Instance();
103 kernel.SetExecutable(executable);
104 Session* session = kernel.CurrentSession();
105 session->fgpid = process->pid;
106 return process->pid;
107 }
108 else
109 {
110 Panic("file '" + programFileName + "' is not a CMSX executable");
111 }
112 return -1;
113 }
114 }