|
|
1.1 ! root 1: .unixorder ! 2: .llen 132 ! 3: .include as.inc ! 4: .text ! 5: .alignoff ! 6: .align 4 ! 7: ! 8: / the init gdt is in the text segment since the data segment ! 9: / is relocated after we switch into 386 mode (when a ! 10: / valid gdt is required) ! 11: ! 12: gdtinit: / used before turning on paging ! 13: .value gdtend-gdt-1 / limit of gdt ! 14: / gdt physical addr is 0x0040_2000+gdt ! 15: .long [[[-SBASE]+PBASE]<<BPCSHIFT]+gdt ! 16: .value 0 ! 17: gdtmap: / used after paging is enabled ! 18: .value gdtend-gdt-1 / limit of gdt ! 19: .long gdt ! 20: .value 0 ! 21: ! 22: idtmap: / used after paging is enabled ! 23: .value 2047 ! 24: .long idt ! 25: .value 0 ! 26: ! 27: //// ! 28: / ! 29: / Macro MEM_SEG specifies a memory segment descriptor. ! 30: / base is 32 bits ! 31: / limit is 20 bits ! 32: / type is 4 bits ! 33: / dpl is 2 bits ! 34: / flags is the 4 high bits of byte at descriptor + 6 ! 35: / 8's bit of flags is limit granularity (0:byte 1:click) ! 36: / 4's bit of flags is default op size (0:16 bit 1:32 bit) ! 37: / ! 38: //// ! 39: ! 40: MEM_SEG .macro base,limit,type,dpl,flags ! 41: .value limit ! 42: .value base ! 43: .byte [base] >> 16 ! 44: .byte 0x90 | [[[dpl] & 3] << 5] | [[type] & 0xF] ! 45: .byte [[[flags] << 4] & 0xF0] | [[[limit] >> 16] & 0xF] ! 46: .byte [base] >> 24 ! 47: .endm ! 48: ! 49: //// ! 50: / ! 51: / Macro TSS_SEG specifies a tss segment descriptor. ! 52: / base is 32 bits ! 53: / limit is 20 bits ! 54: / [type is 0x9] ! 55: / [dpl is 0] ! 56: / gran is limit granularity (0:byte 1:click) ! 57: / ! 58: //// ! 59: ! 60: TSS_SEG .macro base,limit,gran ! 61: .value limit ! 62: .value base ! 63: .byte [base] >> 16 ! 64: .byte 0x89 ! 65: .byte [[[gran] << 7] & 0x80] | [[[limit] >> 16] & 0xF] ! 66: .byte [base] >> 24 ! 67: .endm ! 68: ! 69: //// ! 70: / ! 71: / Macro LDT_SEG specifies a tss segment descriptor. ! 72: / base is 32 bits ! 73: / limit is 20 bits ! 74: / [type is 0x2] ! 75: / [dpl is 0] ! 76: / gran is limit granularity (0:byte 1:click) ! 77: / ! 78: //// ! 79: ! 80: LDT_SEG .macro base,limit,gran ! 81: .value limit ! 82: .value base ! 83: .byte [base] >> 16 ! 84: .byte 0x82 ! 85: .byte [[[gran] << 7] & 0x80] | [[[limit] >> 16] & 0xF] ! 86: .byte [base] >> 24 ! 87: .endm ! 88: ! 89: //// ! 90: / ! 91: / Macro CALL_GATE specifies a call gate descriptor. ! 92: / selector is 16 bits ! 93: / offset is 32 bits ! 94: / dwdcount is 5 bits ! 95: / dpl is 2 bits ! 96: / ! 97: / Would like the following, but can't shift offset since it's a symbol. ! 98: / .value offset ! 99: / .value selector ! 100: / .value 0x8C00 | [[dwdcount] & 0x1F] | [[[dpl] & 3] << 13] ! 101: / .value [offset] >> 16 ! 102: / ! 103: / IMPORTANT!!! ! 104: / This macro does not create a proper call gate. ! 105: / Count on idtinit() to swap 16-bit words at macro+2, macro+6. ! 106: / ! 107: //// ! 108: ! 109: CALL_GATE .macro selector,offset,dwdcount,dpl ! 110: ! 111: .long offset ! 112: .value 0x8C00 | [[dwdcount] & 0x1F] | [[[dpl] & 3] << 13] ! 113: .value selector ! 114: .endm ! 115: ! 116: //// ! 117: / ! 118: / "segment xxxx" below gives the value in a segment register corresponding ! 119: / to the given descriptor. The low 3 bits in a segment register are not ! 120: / used in indexing into the descriptor table. ! 121: / ! 122: //// ! 123: ! 124: .set DPL_0,0 ! 125: .set DPL_1,1 ! 126: .set DPL_2,2 ! 127: .set DPL_3,3 ! 128: ! 129: gdt: ! 130: / segment 0000 ! 131: .long 0,0 / null entry ! 132: ! 133: / segment 0008 - SEG_386_UI ! 134: MEM_SEG 0,0xFFFFF,0xB,DPL_3,0xC ! 135: ! 136: / segment 0010 - SEG_386_UD ! 137: MEM_SEG 0,0xFFFFF,0x3,DPL_3,0xC ! 138: ! 139: / segment 0018 - SEG_RNG0_TXT/SEG_386_KI ! 140: MEM_SEG 0,0xFFFFF,0xB,DPL_0,0xC ! 141: ! 142: / segment 0020 - SEG_386_KD ! 143: MEM_SEG 0,0xFFFFF,0x3,DPL_1,0xC ! 144: ! 145: / segment 0028 - SEG_286_UI ! 146: MEM_SEG 0,0xF,0xB,DPL_3,0x8 ! 147: ! 148: / segment 0030 - SEG_286_UD ! 149: MEM_SEG 0,0xF,0x3,DPL_3,0x8 ! 150: ! 151: / segment 0038 - SEG_TSS ! 152: / limit is 0x68 + (number of bytes in iomap) ! 153: / This allows the required filler byte beyond desired addressing. ! 154: TSS_SEG 0xFFC00000,TSS_IOMAP_OFF+[TSS_IOMAP_LEN .div 8]+3,0 ! 155: ! 156: / segment 0040 - SEG_ROM ! 157: MEM_SEG 0xFFFC0000,0xF,0x3,DPL_0,0x8 ! 158: ! 159: / segment 0048 - SEG_VIDEOa ! 160: MEM_SEG 0xFFFB0000,0xF,0x3,DPL_1,0x8 ! 161: ! 162: / segment 0050 - SEG_VIDEOb ! 163: MEM_SEG 0xFFFA0000,0xF,0x3,DPL_1,0x8 ! 164: ! 165: / segment 0058 - SEG_386_II / init code (text) ! 166: MEM_SEG 0x400000+[PBASE<<BPCSHIFT],0xFFFFF,0xB,DPL_0,0xC ! 167: ! 168: / segment 0060 - SEG_386_ID / init code (data) ! 169: MEM_SEG 0x400000+[PBASE<<BPCSHIFT],0xFFFFF,0x3,DPL_0,0xC ! 170: ! 171: / segment 0068 - SEG_286_UII ! 172: MEM_SEG 0x400000,0xF,0xB,DPL_3,0x8 ! 173: ! 174: / segment 0070 - SEG_LDT ! 175: LDT_SEG 0xFFC00000,0xF,0 ! 176: ! 177: / segment 0078 - SEG_RNG0_STK ! 178: MEM_SEG 0,0xFFBFF,0x7,DPL_0,0xC ! 179: ! 180: / segment 0080 - SEG_RNG1_TXT ! 181: MEM_SEG 0,0xFFFFF,0xB,DPL_1,0xC ! 182: ! 183: / segment 0088 - SEG_RNG1_STK ! 184: MEM_SEG 0,0xFFFFE,0x7,DPL_1,0xC ! 185: ! 186: / Call gates need idtinit() to fix them before they can be used. ! 187: .globl gdtFixBegin ! 188: .globl gdtFixEnd ! 189: gdtFixBegin: ! 190: / segment 0090 - SEG_MMUUPD - Call gate for mmu update ! 191: CALL_GATE SEG_RNG0_TXT,mmuupdfR0,0,DPL_1 ! 192: ! 193: / segment 0098 - SEG_SET_EM - Call gate for writing CR0 EM bit ! 194: CALL_GATE SEG_RNG0_TXT,setEmfR0,1,DPL_1 ! 195: gdtFixEnd: ! 196: gdtend: ! 197: ! 198: / The two entries in the ldt are call gates whose format is somewhat ! 199: / different from the other segment descriptors ! 200: / ! 201: / BCS compatibility requires an LDT ! 202: ! 203: ldt: ! 204: / ldt + 0000 ! 205: CALL_GATE SEG_RNG1_TXT,syc32,1,DPL_3 ! 206: / .long syc32 / call gate for system call ! 207: / .long 0xFFC0EC01 ! 208: ! 209: / ldt + 0008 ! 210: / .long sig32 / call gate for signal return ! 211: / .long 0xFFC0EC01 ! 212: CALL_GATE SEG_RNG1_TXT,sig32,1,DPL_3 ! 213: ldtend: ! 214: ! 215: //// ! 216: / ! 217: / Macro IRPT_GATE specifies a call gate descriptor. ! 218: / selector is 16 bits ! 219: / offset is 32 bits ! 220: / dwdcount is 5 bits ! 221: / dpl is 2 bits ! 222: / ! 223: / Would like the following, but can't shift offset since it's a symbol. ! 224: / .value offset ! 225: / .value selector ! 226: / .value 0x8E00 | [[dwdcount] & 0x1F] | [[[dpl] & 3] << 13] ! 227: / .value [offset] >> 16 ! 228: / ! 229: / IMPORTANT!!! ! 230: / This macro does not create a proper interrupt gate. ! 231: / Count on idtinit() to swap 16-bit words at macro+2, macro+6. ! 232: / ! 233: //// ! 234: ! 235: IRPT_GATE .macro selector,offset,dwdcount,dpl ! 236: ! 237: .long offset ! 238: .value 0x8E00 | [[dwdcount] & 0x1F] | [[[dpl] & 3] << 13] ! 239: .value selector ! 240: .endm ! 241: ! 242: idt: ! 243: IRPT_GATE SEG_RNG1_TXT,trap0,0,DPL_3 ! 244: / IRPT_GATE SEG_RNG0_TXT,trap1_ker,0,DPL_3 / Ring 0 ! 245: IRPT_GATE SEG_RNG1_TXT,trap1_usr,0,DPL_3 / Ring 1 ! 246: IRPT_GATE SEG_RNG1_TXT,trap2,0,DPL_3 ! 247: IRPT_GATE SEG_RNG1_TXT,trap3,0,DPL_3 ! 248: IRPT_GATE SEG_RNG1_TXT,trap4,0,DPL_3 ! 249: IRPT_GATE SEG_RNG1_TXT,trap5,0,DPL_3 ! 250: IRPT_GATE SEG_RNG1_TXT,trap6,0,DPL_3 ! 251: IRPT_GATE SEG_RNG1_TXT,trap7,0,DPL_3 ! 252: IRPT_GATE SEG_RNG1_TXT,trap8,0,DPL_3 ! 253: IRPT_GATE SEG_RNG1_TXT,trap9,0,DPL_3 ! 254: IRPT_GATE SEG_RNG1_TXT,trap10,0,DPL_3 ! 255: IRPT_GATE SEG_RNG1_TXT,trap11,0,DPL_3 ! 256: IRPT_GATE SEG_RNG1_TXT,trap12,0,DPL_3 ! 257: IRPT_GATE SEG_RNG0_TXT,trap13,0,DPL_3 / Ring 0! ! 258: IRPT_GATE SEG_RNG1_TXT,trap14,0,DPL_3 ! 259: .long 0,0 ! 260: IRPT_GATE SEG_RNG1_TXT,trap16,0,DPL_3 ! 261: .org .+0x78 ! 262: IRPT_GATE SEG_RNG1_TXT,clk,0,DPL_3 ! 263: IRPT_GATE SEG_RNG1_TXT,dev1,0,DPL_3 ! 264: IRPT_GATE SEG_RNG1_TXT,dev9,0,DPL_3 ! 265: IRPT_GATE SEG_RNG1_TXT,dev3,0,DPL_3 ! 266: IRPT_GATE SEG_RNG1_TXT,dev4,0,DPL_3 ! 267: IRPT_GATE SEG_RNG1_TXT,dev5,0,DPL_3 ! 268: IRPT_GATE SEG_RNG1_TXT,dev6,0,DPL_3 ! 269: IRPT_GATE SEG_RNG1_TXT,dev7,0,DPL_3 ! 270: .org .+0x240 ! 271: IRPT_GATE SEG_RNG1_TXT,dev8,0,DPL_3 ! 272: IRPT_GATE SEG_RNG1_TXT,dev9,0,DPL_3 ! 273: IRPT_GATE SEG_RNG1_TXT,dev10,0,DPL_3 ! 274: IRPT_GATE SEG_RNG1_TXT,dev11,0,DPL_3 ! 275: IRPT_GATE SEG_RNG1_TXT,dev12,0,DPL_3 ! 276: IRPT_GATE SEG_RNG1_TXT,dev13,0,DPL_3 ! 277: IRPT_GATE SEG_RNG1_TXT,dev14,0,DPL_3 ! 278: IRPT_GATE SEG_RNG1_TXT,dev15,0,DPL_3 ! 279: .org .+0x40 ! 280: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 281: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 282: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 283: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 284: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 285: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 286: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 287: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 288: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 289: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 290: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 291: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 292: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 293: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 294: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 295: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 296: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 297: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 298: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 299: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 300: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 301: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 302: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 303: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 304: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 305: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 306: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 307: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 308: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 309: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 310: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 311: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 312: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 313: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 314: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 315: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 316: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 317: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 318: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 319: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 320: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 321: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 322: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 323: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 324: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 325: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 326: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 327: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 328: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 329: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 330: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 331: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 332: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 333: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 334: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 335: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 336: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 337: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 338: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 339: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 340: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 341: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 342: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 343: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 344: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 345: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 346: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 347: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 348: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 349: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 350: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 351: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 352: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 353: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 354: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 355: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 356: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 357: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 358: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 359: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 360: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 361: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 362: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 363: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 364: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 365: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 366: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 367: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 368: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 369: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 370: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 371: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 372: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 373: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 374: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 375: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 376: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 377: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 378: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 379: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 380: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 381: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 382: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 383: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 384: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 385: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 386: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 387: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 388: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 389: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 390: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 391: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 392: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 393: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 394: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 395: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 396: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 397: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 398: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 399: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 400: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 401: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 402: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 403: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 404: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 405: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 406: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 407: IRPT_GATE SEG_RNG1_TXT,syc,0,DPL_3 ! 408: .long 0 ! 409: idtend: ! 410: .align 4 ! 411: .long 0,0,0,0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.