00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "rZero.h"
00023 #include "rdoff.h"
00024
00025 #define CHECK_FLAG(flags,bit) ((flags) & (1 << (bit)))
00026
00027
00028
00029
00030
00031
00032
00033 rZeroSymbolInfo rZeroExports[] = {
00034 { "consoleClear" , (long)consoleClear , 0 },
00035 { "consoleOut" , (long)printf , 0 },
00036 { "inportb" , (long)inportb , 0 },
00037 { "memcpy" , (long)memcpy , 0 },
00038 { "memoryAllocPage", (long)memoryAllocPage, 0 },
00039 { "memoryFreePage" , (long)memoryFreePage , 0 },
00040 { "memset" , (long)memset , 0 },
00041 { "outportb" , (long)outportb , 0 },
00042 { "outportw" , (long)outportw , 0 },
00043
00044 { "strcmp" , (long)strcmp , 0 },
00045 { "strncmp" , (long)strncmp , 0 },
00046 { "timerGetTicks" , (long)timerGetTicks , 0 },
00047 { (char *)NULL , NULL , 0 }
00048 };
00049
00050
00051
00052
00053
00054
00055
00056 rZeroSymbolInfo rZeroImports[] = {
00057 {"_main" , NULL, 0 },
00058 { "main" , NULL, 0 },
00059 { "splashPrint" , NULL, 0 },
00060 { "splashProgress", NULL, 0 },
00061 { "splashScreen" , NULL, 0 },
00062 { "taskNew" , NULL, 0 },
00063 { "taskSwitch" , NULL, 0 },
00064 { (char *)NULL , NULL, 0 }
00065 };
00066
00067 void rZeroInit(void) {
00068 module_t *mod;
00069 rZeroObj obj;
00070 int i;
00071
00072
00073 if( !CHECK_FLAG(multibootInfo->flags, 3)) {
00074 consoleOut("No rZero Modules Found!!!\n");
00075 consoleOut("The following modules:\n");
00076 consoleOut(" scheduler.r0\n");
00077 consoleOut(" progress.r0\n");
00078 consoleOut("are required by ndk!\n");
00079
00080 }
00081
00082 consoleOut("Total rZero Modules: %d, Starting at: 0x%8x\n",
00083 (int)multibootInfo->mods_count,
00084 (int)multibootInfo->mods_addr);
00085
00086
00087
00088
00089 mod = (module_t *) multibootInfo->mods_addr;
00090 for(i = 0; i < multibootInfo->mods_count; i++) {
00091 obj.mem = (char *)mod[i].mod_start;
00092 obj.end = (char *)mod[i].mod_end;
00093 obj.name = (char *)mod[i].string;
00094 rZeroClearSegments();
00095 rZeroParse(&obj);
00096
00097 }
00098 return;
00099 }
00100
00101
00102
00103
00104
00105 void rZeroClearSegments(void) {
00106 int i = 0;
00107 while(rZeroExports[i].symbolName != NULL) {
00108 rZeroExports[i++].segmentNum = 0;
00109 }
00110 }
00111
00112
00113
00114
00115 int rZeroFindSymbol(char *symbol, rZeroSymbolInfo *symInfo) {
00116 int i = 0;
00117
00118
00119 while(strcmp(symbol, symInfo[i].symbolName) != 0) {
00120 if(symInfo[i].symbolName == 0) {
00121 consoleOut("Could not find symbol: %s\n", symbol);
00122 return -1;
00123 }
00124 i++;
00125 }
00126 return i;
00127 }
00128
00129
00130
00131
00132 int rZeroFindSegment(short segment, rZeroSymbolInfo *symInfo) {
00133 int i = 0;
00134 while(symInfo[i].segmentNum != segment) i++;
00135
00136 return i;
00137 }
00138
00139
00140
00141
00142
00143
00144
00145 void rZeroParse(rZeroObj *obj) {
00146
00147 if(strncmp(obj->mem, "RDOFF", 5)) {
00148 consoleOut("rZero module (%s) not in RDOFF format\n", obj->name);
00149 return;
00150 } else {
00151 obj->version = obj->mem[5] - '0';
00152 consoleOut("RDOFF Version %d.0\n", obj->version);
00153 }
00154
00155 obj->pos = 6;
00156
00157
00158
00159 if(obj->version > 1) {
00160 obj->length = readLong(obj);
00161 consoleOut("Object content size: %d bytes\n", (int)obj->length);
00162 }
00163
00164
00165 obj->headerLength = readLong(obj);
00166 obj->headerOffset = obj->pos;
00167
00168
00169 obj->pos += obj->headerLength;
00170
00171
00172 rZeroParseSegments(obj);
00173
00174
00175 obj->pos = obj->headerOffset;
00176
00177
00178 consoleOut("Header (%d bytes):\n", obj->headerLength);
00179 rZeroParseHeader(obj);
00180
00181 return;
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 void rZeroParseHeader(rZeroObj *obj) {
00193 char buf[129], type, segment, length, flags;
00194 unsigned char recordLength;
00195 long offset, labelLength;
00196 short refSegment;
00197 long headerLength;
00198
00199 char isRelative;
00200 long symbolIndex;
00201 long relocation;
00202 char *segReloc;
00203
00204
00205 headerLength = obj->headerLength;
00206 while (headerLength > 0) {
00207
00208 type = readByte(obj);
00209
00210
00211 if (obj->version >= 2) {
00212 recordLength = readByte(obj);
00213 }
00214
00215
00216 switch(type) {
00217
00218 case 1:
00219 case 6:
00220 consoleOut("relocation (%d) :", type);
00221 segment = readByte(obj);
00222 offset = readLong(obj);
00223 length = readByte(obj);
00224 refSegment = readShort(obj);
00225 consoleOut("seg: %x, offs %x, len %x, refSeg %x\n", segment, offset, length, refSegment);
00226
00227
00228
00229 if(refSegment < 3) {
00230 relocation = (long)obj->mem + obj->segment[refSegment].offset;
00231 }
00232
00233 else {
00234
00235
00236
00237 symbolIndex = rZeroFindSegment(refSegment, rZeroExports);
00238
00239
00240 relocation = rZeroExports[symbolIndex].symbolLocation;
00241
00242 }
00243
00244 isRelative = ((segment & 64) == 64);
00245 segment &= 63;
00246
00247
00248
00249
00250 if( isRelative )
00251 relocation -= (long)obj->mem + obj->segment[ segment ].offset;
00252
00253
00254
00255 if(segment == 0) segReloc = (char *)obj->mem + obj->segment[0].offset;
00256 else if(segment == 1) segReloc = (char *)obj->mem + obj->segment[1].offset;
00257 else {
00258
00259 consoleOut("relocation not needed here!\n");
00260 continue;
00261 }
00262
00263
00264 consoleOut("obj->mem: %x, obj->mem + seg[0].off %x\n",
00265 obj->mem,
00266 obj->mem + obj->segment[ segment ].offset);
00267 consoleOut("patching area: %x + %x with %x\n", (long)segReloc,
00268 (long)offset,
00269 (long)relocation);
00270
00271
00272 switch(length) {
00273 case 1:
00274 segReloc[offset] += (char)relocation;
00275 break;
00276 case 2:
00277 *(short *)(segReloc + offset) += (short)relocation;
00278 break;
00279 case 4:
00280
00281 *(long *)(segReloc + offset) += (long)relocation;
00282 break;
00283 default:
00284 consoleOut("unknown relocation size!\n");
00285 break;
00286 }
00287
00288
00289
00290
00291
00292 if(obj->version >= 2 && recordLength != 8)
00293 consoleOut("warning: reclen != 8\n");
00294 if(obj->version == 1)
00295 headerLength -= 9;
00296 if(obj->version == 1 && type == 6)
00297 consoleOut("warning: seg relocation not supported in RDOFF1\n");
00298 break;
00299
00300 case 2:
00301 case 7:
00302 consoleOut("import: ");
00303
00304 refSegment = readShort(obj);
00305 labelLength = 0;
00306
00307
00308
00309 if (obj->version == 1) {
00310 do {
00311 buf[labelLength] = readByte(obj);
00312 } while (buf[labelLength++]);
00313 } else {
00314 for (;labelLength < recordLength - 2; labelLength++)
00315 buf[labelLength] = readByte(obj);
00316 }
00317 consoleOut("%s\n", buf);
00318
00319
00320
00321
00322 if (obj->version == 1) headerLength -= labelLength + 3;
00323
00324
00325 if (obj->version == 1 && type == 7)
00326 consoleOut (" warning: far import not supported in RDOFF1\n");
00327
00328
00329
00330 symbolIndex = rZeroFindSymbol(buf, rZeroExports);
00331 if(symbolIndex == -1) consoleOut("Cannot find!\n");
00332 rZeroExports[symbolIndex].segmentNum = refSegment;
00333 break;
00334
00335 case 3:
00336 consoleOut("export: ");
00337 flags = readByte(obj);
00338 segment = readByte(obj);
00339 offset = readLong(obj);
00340 labelLength = 0;
00341
00342
00343 if (obj->version == 1) {
00344 do {
00345 buf[labelLength] = readByte(obj);
00346 } while (buf[labelLength++]);
00347 } else {
00348 for (; labelLength < recordLength - 6; labelLength++)
00349 buf[labelLength] = readByte(obj);
00350 }
00351 consoleOut("%s\n", buf);
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 if (obj->version == 1) headerLength -= labelLength + 6;
00364
00365
00366 symbolIndex = rZeroFindSymbol(buf, rZeroImports);
00367 if(symbolIndex != -1)
00368 rZeroImports[symbolIndex].symbolLocation =
00369 (long)obj->mem + obj->segment[segment].offset + offset;
00370 else consoleOut("couldn't export\n");
00371
00372 break;
00373
00374 case 4:
00375 case 8:
00376 labelLength = 0;
00377
00378
00379 if(obj->version == 1) {
00380 do {
00381 buf[labelLength] = readByte(obj);
00382 } while (buf[labelLength++]);
00383 } else {
00384 for (; labelLength < recordLength; labelLength++)
00385 buf[labelLength] = readByte(obj);
00386 }
00387
00388
00389
00390 if (type == 4) consoleOut(" requires dll: %s\n", buf);
00391 else consoleOut(" requires module: %s\n", buf);
00392
00393
00394 if (obj->version == 1) headerLength -= labelLength + 1;
00395 break;
00396 case 5:
00397 labelLength = readLong(obj);
00398
00399
00400 consoleOut(" bss reservation: %8x bytes\n", labelLength);
00401
00402
00403 if (obj->version == 1) headerLength -= 5;
00404 if (obj->version > 1 && recordLength != 4)
00405 consoleOut(" warning: reclen != 4\n");
00406 break;
00407
00408 case 9:
00409 consoleOut(" MultiBoot header included!\n");
00410 consoleOut(" Currently unsupported in rZero modules.\nSkipping over\n");
00411
00412 break;
00413 default:
00414
00415 consoleOut(" unrecognised record (type %d", (int)type);
00416 if (obj->version > 1) {
00417 consoleOut(", length %d)\n",(int)recordLength);
00418 obj->pos += recordLength;
00419 }
00420
00421
00422 if (obj->version == 1) headerLength --;
00423 }
00424
00425 if (obj->version != 1) headerLength -= 2 + recordLength;
00426 }
00427 }
00428
00429
00430
00431
00432 void rZeroParseSegments(rZeroObj *obj) {
00433 short segType;
00434 int i;
00435
00436
00437 obj->numSegments = 0;
00438 segType = readShort(obj);
00439 while(segType != 0 ) {
00440 obj->segment[obj->numSegments].type = segType;
00441 obj->segment[obj->numSegments].number = readShort(obj);
00442 obj->segment[obj->numSegments].reserved = readShort(obj);
00443 obj->segment[obj->numSegments].length = readLong(obj);
00444 obj->segment[obj->numSegments].offset = obj->pos;
00445
00446
00447 obj->pos += obj->segment[obj->numSegments].length;
00448 obj->numSegments++;
00449
00450 segType = readShort(obj);
00451 }
00452
00453
00454 consoleOut("%d segments:\n", obj->numSegments);
00455 for(i = 0; i < obj->numSegments; i++) {
00456 consoleOut("Type %d, Number %d, Reserved %d, Length %d, Offset %d\n",
00457 obj->segment[i].type,
00458 obj->segment[i].number,
00459 obj->segment[i].reserved,
00460 obj->segment[i].length,
00461 obj->segment[i].offset);
00462 }
00463 return;
00464 }
00465
00466
00467
00468
00469
00470 long volatile readLong(rZeroObj *obj) {
00471 char *start = &obj->mem[obj->pos];
00472 long r = 0;
00473
00474
00475
00476
00477
00478
00479
00480
00481 r = *(long *)start;
00482
00483 obj->pos += 4;
00484 return r;
00485 }
00486
00487 short volatile readShort(rZeroObj *obj) {
00488 char *start = &obj->mem[obj->pos];
00489 short r = 0;
00490
00491
00492 r = *(short *)start;
00493
00494 obj->pos += 2;
00495 return r;
00496 }
00497
00498 char volatile readByte(rZeroObj *obj) {
00499 return obj->mem[obj->pos++];
00500 }