| 1 | ;
|
|---|
| 2 | ; LOADER.ASM -- Load executable files
|
|---|
| 3 | ;
|
|---|
| 4 | ; Copyright (c) 1991-1995 by Eberhard Mattes
|
|---|
| 5 | ;
|
|---|
| 6 | ; This file is part of emx.
|
|---|
| 7 | ;
|
|---|
| 8 | ; emx is free software; you can redistribute it and/or modify it
|
|---|
| 9 | ; under the terms of the GNU General Public License as published by
|
|---|
| 10 | ; the Free Software Foundation; either version 2, or (at your option)
|
|---|
| 11 | ; any later version.
|
|---|
| 12 | ;
|
|---|
| 13 | ; emx is distributed in the hope that it will be useful,
|
|---|
| 14 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 15 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|---|
| 16 | ; GNU General Public License for more details.
|
|---|
| 17 | ;
|
|---|
| 18 | ; You should have received a copy of the GNU General Public License
|
|---|
| 19 | ; along with emx; see the file COPYING. If not, write to
|
|---|
| 20 | ; the Free Software Foundation, 59 Temple Place - Suite 330,
|
|---|
| 21 | ; Boston, MA 02111-1307, USA.
|
|---|
| 22 | ;
|
|---|
| 23 | ; See emx.asm for a special exception.
|
|---|
| 24 | ;
|
|---|
| 25 |
|
|---|
| 26 | INCLUDE EMX.INC
|
|---|
| 27 | INCLUDE TABLES.INC
|
|---|
| 28 | INCLUDE PAGING.INC
|
|---|
| 29 | INCLUDE SEGMENTS.INC
|
|---|
| 30 | INCLUDE MEMORY.INC
|
|---|
| 31 | INCLUDE PMIO.INC
|
|---|
| 32 | INCLUDE MISC.INC
|
|---|
| 33 | INCLUDE SIGNAL.INC
|
|---|
| 34 | INCLUDE PROCESS.INC
|
|---|
| 35 | INCLUDE SYMBOLS.INC
|
|---|
| 36 | INCLUDE DEBUG.INC
|
|---|
| 37 | INCLUDE PMINT.INC
|
|---|
| 38 | INCLUDE HEADERS.INC
|
|---|
| 39 | INCLUDE OPTIONS.INC
|
|---|
| 40 | INCLUDE ERRORS.INC
|
|---|
| 41 | INCLUDE VERSION.INC
|
|---|
| 42 |
|
|---|
| 43 | PUBLIC LOADER
|
|---|
| 44 |
|
|---|
| 45 | HEADER_SIZE = SIZE A_OUT_HEADER
|
|---|
| 46 | IF (SIZE EXE1_HEADER) GT HEADER_SIZE
|
|---|
| 47 | HEADER_SIZE = SIZE EXE1_HEADER
|
|---|
| 48 | ENDIF
|
|---|
| 49 |
|
|---|
| 50 | SV_DATA SEGMENT
|
|---|
| 51 |
|
|---|
| 52 | SYM_SIZE DWORD ?
|
|---|
| 53 | STR_SIZE DWORD ?
|
|---|
| 54 | TEXT_PAGE DWORD ?
|
|---|
| 55 | DATA_PAGE DWORD ?
|
|---|
| 56 |
|
|---|
| 57 | ;
|
|---|
| 58 | ; The file header (this buffer is used for different types of headers)
|
|---|
| 59 | ;
|
|---|
| 60 | HDR_E LABEL EXE1_HEADER
|
|---|
| 61 | HDR_A LABEL A_OUT_HEADER
|
|---|
| 62 | HDR BYTE HEADER_SIZE DUP (?)
|
|---|
| 63 |
|
|---|
| 64 | ;
|
|---|
| 65 | ; The emxbind patch area
|
|---|
| 66 | ;
|
|---|
| 67 | HDR_B BIND_HEADER <>
|
|---|
| 68 |
|
|---|
| 69 | ;
|
|---|
| 70 | ; The layout table (aka OS/2 patch area)
|
|---|
| 71 | ;
|
|---|
| 72 | HDR_L LAYOUT_TABLE <>
|
|---|
| 73 |
|
|---|
| 74 | $CANT_OPEN BYTE "Cannot open program file", CR, LF, 0
|
|---|
| 75 | $CANT_READ BYTE "Cannot read program file", CR, LF, 0
|
|---|
| 76 | $INVALID_PROG BYTE "Invalid program file", CR, LF, 0
|
|---|
| 77 | $INVALID_VER BYTE "Wrong emx version", CR, LF, 0
|
|---|
| 78 | $LOADER_MEM BYTE "Out of memory", CR, LF, 0
|
|---|
| 79 | $INV_OPT BYTE "Invalid emx option", CR, LF, 0
|
|---|
| 80 |
|
|---|
| 81 | SV_DATA ENDS
|
|---|
| 82 |
|
|---|
| 83 |
|
|---|
| 84 |
|
|---|
| 85 | SV_CODE SEGMENT
|
|---|
| 86 |
|
|---|
| 87 | ;
|
|---|
| 88 | ; Load executable file, called by NEW_PROCESS
|
|---|
| 89 | ;
|
|---|
| 90 | ; In: DI Pointer to process entry
|
|---|
| 91 | ; AX:EDX Pointer to file name
|
|---|
| 92 | ;
|
|---|
| 93 | ; Out: AX Return code (0:ok)
|
|---|
| 94 | ; EDX Error message (for AX > 0)
|
|---|
| 95 | ;
|
|---|
| 96 |
|
|---|
| 97 | ASSUME CS:SV_CODE, DS:SV_DATA
|
|---|
| 98 |
|
|---|
| 99 | ASSUME DI:PTR PROCESS
|
|---|
| 100 | LOADER PROC NEAR
|
|---|
| 101 | CALL L_OPEN ; Open the file
|
|---|
| 102 | OR AX, AX
|
|---|
| 103 | JNZ SHORT LOADER_RET
|
|---|
| 104 | CALL L_HEADER ; Read header
|
|---|
| 105 | OR AX, AX
|
|---|
| 106 | JNZ SHORT LOADER_CLOSE
|
|---|
| 107 | CALL L_OPTIONS ; Parse emx options
|
|---|
| 108 | OR AX, AX
|
|---|
| 109 | JNZ SHORT LOADER_CLOSE
|
|---|
| 110 | CALL L_LAYOUT ; Compute memory layout
|
|---|
| 111 | OR AX, AX
|
|---|
| 112 | JNZ SHORT LOADER_CLOSE
|
|---|
| 113 | CALL L_VMEM ; Allocate virtual memory
|
|---|
| 114 | OR AX, AX
|
|---|
| 115 | JNZ SHORT LOADER_CLOSE
|
|---|
| 116 | CALL L_SYMBOLS ; Load symbols
|
|---|
| 117 | OR AX, AX
|
|---|
| 118 | JNZ SHORT LOADER_CLOSE
|
|---|
| 119 | CALL L_PRELOAD ; Preload
|
|---|
| 120 | OR AX, AX
|
|---|
| 121 | JZ SHORT LOADER_RET
|
|---|
| 122 | LOADER_CLOSE: PUSH AX
|
|---|
| 123 | PUSH EDX
|
|---|
| 124 | MOV BX, [DI].P_EXEC_HANDLE
|
|---|
| 125 | CALL CLOSE
|
|---|
| 126 | POP EDX
|
|---|
| 127 | POP AX
|
|---|
| 128 | LOADER_RET: RET
|
|---|
| 129 | ASSUME DI:NOTHING
|
|---|
| 130 |
|
|---|
| 131 | ;
|
|---|
| 132 | ; Open the file
|
|---|
| 133 | ;
|
|---|
| 134 | ASSUME DI:PTR PROCESS
|
|---|
| 135 | L_OPEN PROC NEAR
|
|---|
| 136 | MOV CL, 20H ; Deny write; read access
|
|---|
| 137 | CALL OPEN ; Open executable file
|
|---|
| 138 | JC SHORT L_OPEN_ERROR ; Error -> fail
|
|---|
| 139 | MOV [DI].P_EXEC_HANDLE, AX ; Save handle
|
|---|
| 140 | MOV BX, AX ; Return handle in BX
|
|---|
| 141 | XOR AX, AX ; No error
|
|---|
| 142 | RET
|
|---|
| 143 |
|
|---|
| 144 | L_OPEN_ERROR: MOV AX, ENOENT ; Return error code
|
|---|
| 145 | LEA EDX, $CANT_OPEN ; and error message
|
|---|
| 146 | RET
|
|---|
| 147 | ASSUME DI:NOTHING
|
|---|
| 148 | L_OPEN ENDP
|
|---|
| 149 |
|
|---|
| 150 |
|
|---|
| 151 | ;
|
|---|
| 152 | ; Read the header
|
|---|
| 153 | ;
|
|---|
| 154 | ASSUME DI:PTR PROCESS
|
|---|
| 155 | L_HEADER PROC NEAR
|
|---|
| 156 | MOV HDR_B.BND_OPTIONS[0], 0 ; This is for plain a.out files
|
|---|
| 157 | XOR EDX, EDX ; Read header at location 0
|
|---|
| 158 | NEXT_HEADER: MOV [DI].P_EXEC_OFFSET, EDX ; Set offset
|
|---|
| 159 | CALL SEEK ; Move to header
|
|---|
| 160 | MOV ECX, SIZE HDR ; Size of biggest header
|
|---|
| 161 | LEA EDX, HDR
|
|---|
| 162 | MOV AX, DS
|
|---|
| 163 | CALL READ ; Read header
|
|---|
| 164 | JC READ_ERROR ; Error -> fail
|
|---|
| 165 | JNZ INVALID_PROG
|
|---|
| 166 | CMP HDR_E.EXE_MAGIC, 5A4DH ; exe?
|
|---|
| 167 | JNE SHORT LH_10 ; No -> not bound
|
|---|
| 168 | ;
|
|---|
| 169 | ; It's an exe file, which works only if it's a bound executable
|
|---|
| 170 | ;
|
|---|
| 171 | CMP [DI].P_EXEC_OFFSET, 0 ; First header?
|
|---|
| 172 | JNE INVALID_PROG ; No -> error
|
|---|
| 173 | MOVZX EDX, HDR_E.EXE_HDR_SIZE ; Header size (paragraphs)
|
|---|
| 174 | SHL EDX, 4 ; Header size (bytes)
|
|---|
| 175 | CALL SEEK ; Start of image
|
|---|
| 176 | MOV ECX, SIZE HDR_B
|
|---|
| 177 | LEA EDX, HDR_B
|
|---|
| 178 | MOV AX, DS
|
|---|
| 179 | CALL READ ; Read patch area
|
|---|
| 180 | JC READ_ERROR ; Error -> fail
|
|---|
| 181 | JNZ INVALID_PROG
|
|---|
| 182 | ASSUME DI:NOTHING
|
|---|
| 183 | PUSH ES
|
|---|
| 184 | PUSH SI
|
|---|
| 185 | PUSH DI
|
|---|
| 186 | MOV AX, G_HDR_SEL
|
|---|
| 187 | MOV ES, AX
|
|---|
| 188 | ASSUME ES:HDR_SEG
|
|---|
| 189 | XOR DI, DI
|
|---|
| 190 | LEA SI, HDR_B ; Compare signature and
|
|---|
| 191 | MOV CX, HDR_VERSION_LEN ; version
|
|---|
| 192 | CLD
|
|---|
| 193 | REPE CMPS BYTE PTR DS:[SI], BYTE PTR ES:[DI]
|
|---|
| 194 | POP DI
|
|---|
| 195 | POP SI
|
|---|
| 196 | POP ES
|
|---|
| 197 | JE SHORT SIG_OK ; Match -> ok
|
|---|
| 198 | MOV AX, HDR_VERSION_LEN
|
|---|
| 199 | SUB AX, CX ; Length of common prefix + 1
|
|---|
| 200 | CMP AX, HDR_EMX_LEN
|
|---|
| 201 | JBE INVALID_PROG ; Different signature -> fail
|
|---|
| 202 | ;
|
|---|
| 203 | ; Version check is disabled. Leave checking the version to the C runtime
|
|---|
| 204 | ; startup code, assuming that all DOS calls and system calls required for
|
|---|
| 205 | ; checking the version and displaying the error message are supported by
|
|---|
| 206 | ; all versions of emx.exe (or, vice versa: emx.exe supports the check done
|
|---|
| 207 | ; by the startup code for all versions of the C runtime library).
|
|---|
| 208 | ;
|
|---|
| 209 | ;;;; JMP INVALID_VERSION ; Different version -> fail
|
|---|
| 210 |
|
|---|
| 211 | ASSUME ES:NOTHING
|
|---|
| 212 | SIG_OK: CMP HDR_B.BND_BIND_FLAG, FALSE
|
|---|
| 213 | JE INVALID_PROG ; Not bound ->
|
|---|
| 214 | MOV EDX, HDR_B.BND_HDR_LOC
|
|---|
| 215 | JMP NEXT_HEADER ; Redo with next header
|
|---|
| 216 |
|
|---|
| 217 | ;
|
|---|
| 218 | ; Check for a.out header
|
|---|
| 219 | ;
|
|---|
| 220 | ASSUME DI:PTR PROCESS
|
|---|
| 221 | LH_10: CMP HDR_A.A_MAGIC, A_OUT_MAGIC ; GNU a.out -z ?
|
|---|
| 222 | JNE INVALID_PROG ; No -> error
|
|---|
| 223 | ADD [DI].P_EXEC_OFFSET, A_OUT_OFFSET - 1000H
|
|---|
| 224 | CMP HDR_A.A_TEXT_SIZE, 0
|
|---|
| 225 | JZ INVALID_PROG
|
|---|
| 226 | CMP HDR_A.A_ENTRY, 10000H ; Guard against old a.out files
|
|---|
| 227 | JNE INVALID_PROG
|
|---|
| 228 | ;
|
|---|
| 229 | ; Read the layout table, which is required for retrieving the brk
|
|---|
| 230 | ; pointer of a dumped heap. The layout table is located at the
|
|---|
| 231 | ; beginning of the data segment.
|
|---|
| 232 | ;
|
|---|
| 233 | MOV EDX, HDR_A.A_TEXT_SIZE
|
|---|
| 234 | ADD EDX, 0FFFH ; Round
|
|---|
| 235 | AND EDX, NOT 0FFFH
|
|---|
| 236 | ADD EDX, [DI].P_EXEC_OFFSET
|
|---|
| 237 | ADD EDX, 1000H ; See P_EXEC_OFFSET above
|
|---|
| 238 | CALL SEEK ; Move to layout table
|
|---|
| 239 | MOV ECX, SIZE HDR_L
|
|---|
| 240 | LEA EDX, HDR_L
|
|---|
| 241 | MOV AX, DS
|
|---|
| 242 | CALL READ ; Read header
|
|---|
| 243 | JC READ_ERROR ; Error -> fail
|
|---|
| 244 | JNZ INVALID_PROG
|
|---|
| 245 | ;
|
|---|
| 246 | ; Check the layout table
|
|---|
| 247 | ;
|
|---|
| 248 | CMP HDR_L.L_TEXT_BASE, 10000H
|
|---|
| 249 | JNE INVALID_PROG
|
|---|
| 250 | MOV AL, BYTE PTR HDR_L.L_FLAGS[3]
|
|---|
| 251 | MOV [DI].P_INTERFACE, AL ; Set interface version
|
|---|
| 252 | XOR AX, AX ; No error
|
|---|
| 253 | RET
|
|---|
| 254 | L_HEADER ENDP
|
|---|
| 255 |
|
|---|
| 256 | ;
|
|---|
| 257 | ; Parse options.
|
|---|
| 258 | ;
|
|---|
| 259 | ; 1/ emxbind patch area
|
|---|
| 260 | ; 2/ EMXOPT environment variable
|
|---|
| 261 | ; 3/ command line (first process only)
|
|---|
| 262 | ;
|
|---|
| 263 | L_OPTIONS PROC NEAR
|
|---|
| 264 | ;
|
|---|
| 265 | ; Process the emxbind patch area
|
|---|
| 266 | ;
|
|---|
| 267 | MOV_ES_DS
|
|---|
| 268 | LEA ESI, HDR_B.BND_OPTIONS
|
|---|
| 269 | CALL PM_OPTIONS
|
|---|
| 270 | JC SHORT LO_ERROR
|
|---|
| 271 | ;
|
|---|
| 272 | ;
|
|---|
| 273 | ; Process the EMXOPT environment variable if present.
|
|---|
| 274 | ;
|
|---|
| 275 | MOV AX, G_ENV_SEL
|
|---|
| 276 | MOV ES, AX
|
|---|
| 277 | MOVZX ESI, ENV_EMXOPT
|
|---|
| 278 | OR ESI, ESI
|
|---|
| 279 | JZ SHORT LO_10
|
|---|
| 280 | CALL PM_OPTIONS
|
|---|
| 281 | JC SHORT LO_ERROR
|
|---|
| 282 | ;
|
|---|
| 283 | ; Process the command line options. Note that CMDL_OPTIONS[0] is
|
|---|
| 284 | ; set to 0 after starting the first process. That is, all processes
|
|---|
| 285 | ; but the initial one ignore the command line options.
|
|---|
| 286 | ;
|
|---|
| 287 | LO_10: MOV_ES_DS
|
|---|
| 288 | LEA ESI, CMDL_OPTIONS
|
|---|
| 289 | CALL PM_OPTIONS
|
|---|
| 290 | JC SHORT LO_ERROR
|
|---|
| 291 | XOR AX, AX ; No error
|
|---|
| 292 | RET
|
|---|
| 293 |
|
|---|
| 294 | LO_ERROR: MOV AX, ENOEXEC ; Error:
|
|---|
| 295 | LEA EDX, $INV_OPT ; Invalid emx option
|
|---|
| 296 | RET
|
|---|
| 297 | L_OPTIONS ENDP
|
|---|
| 298 |
|
|---|
| 299 | ;
|
|---|
| 300 | ; Compute the memory layout of the process
|
|---|
| 301 | ;
|
|---|
| 302 | L_LAYOUT PROC NEAR
|
|---|
| 303 | MOV EAX, HDR_A.A_ENTRY
|
|---|
| 304 | MOV [DI].P_ENTRY_POINT, EAX ; Set entry point
|
|---|
| 305 | MOV [DI].P_TEXT_OFF, EAX
|
|---|
| 306 | MOV EAX, HDR_A.A_TEXT_SIZE
|
|---|
| 307 | MOV [DI].P_TEXT_SIZE, EAX ; Set size of text segment
|
|---|
| 308 | MOV EAX, HDR_A.A_DATA_SIZE
|
|---|
| 309 | MOV [DI].P_DATA_SIZE, EAX
|
|---|
| 310 | MOV EAX, [DI].P_TEXT_OFF
|
|---|
| 311 | ADD EAX, HDR_A.A_TEXT_SIZE
|
|---|
| 312 | DEC EAX
|
|---|
| 313 | AND EAX, NOT 0FFFFH
|
|---|
| 314 | ADD EAX, 10000H
|
|---|
| 315 | MOV [DI].P_DATA_OFF, EAX
|
|---|
| 316 | ;
|
|---|
| 317 | ; Compute offset of bss segment
|
|---|
| 318 | ;
|
|---|
| 319 | ADD EAX, HDR_A.A_DATA_SIZE
|
|---|
| 320 | MOV [DI].P_BSS_OFF, EAX
|
|---|
| 321 | ;
|
|---|
| 322 | ; Compute address of heap: If the heap is loaded from the executable,
|
|---|
| 323 | ; use the heap base address and the brk pointer from the layout table.
|
|---|
| 324 | ; Otherwise, put the heap after the BSS
|
|---|
| 325 | ;
|
|---|
| 326 | MOV EAX, HDR_L.L_HEAP_BRK
|
|---|
| 327 | OR EAX, EAX ; Preloaded heap?
|
|---|
| 328 | JZ SHORT LL_HEAP_1 ; No ->
|
|---|
| 329 | MOV [DI].P_BRK, EAX
|
|---|
| 330 | MOV EAX, HDR_L.L_HEAP_BASE
|
|---|
| 331 | MOV [DI].P_INIT_BRK, EAX
|
|---|
| 332 | JMP SHORT LL_HEAP_9
|
|---|
| 333 |
|
|---|
| 334 | LL_HEAP_1: MOV EAX, [DI].P_BSS_OFF
|
|---|
| 335 | ADD EAX, HDR_A.A_BSS_SIZE
|
|---|
| 336 | DEC EAX ; Align to 64K
|
|---|
| 337 | AND EAX, NOT 0FFFFH
|
|---|
| 338 | ADD EAX, 10000H
|
|---|
| 339 | MOV [DI].P_BRK, EAX
|
|---|
| 340 | MOV [DI].P_INIT_BRK, EAX
|
|---|
| 341 | LL_HEAP_9:
|
|---|
| 342 | ;
|
|---|
| 343 | ; Compute address of stack
|
|---|
| 344 | ;
|
|---|
| 345 | MOV EAX, [DI].P_INIT_BRK ; Heap base address
|
|---|
| 346 | AND EAX, NOT 0FFFH
|
|---|
| 347 | ADD EAX, 1000H
|
|---|
| 348 | ADD EAX, [DI].P_STACK_SIZE
|
|---|
| 349 | MOV [DI].P_STACK_ADDR, EAX
|
|---|
| 350 | MOV [DI].P_DSEG_SIZE, EAX
|
|---|
| 351 | ;
|
|---|
| 352 | ; Compute page numbers
|
|---|
| 353 | ;
|
|---|
| 354 | MOV ECX, 1
|
|---|
| 355 | MOV TEXT_PAGE, ECX
|
|---|
| 356 | MOV EAX, [DI].P_TEXT_SIZE
|
|---|
| 357 | ADD EAX, 0FFFH
|
|---|
| 358 | SHR EAX, 12
|
|---|
| 359 | ADD ECX, EAX
|
|---|
| 360 | MOV DATA_PAGE, ECX
|
|---|
| 361 | MOV EAX, [DI].P_DATA_SIZE
|
|---|
| 362 | ADD EAX, 0FFFH
|
|---|
| 363 | SHR EAX, 12
|
|---|
| 364 | ADD ECX, EAX
|
|---|
| 365 | MOV [DI].P_SYM_PAGE, ECX
|
|---|
| 366 | ;
|
|---|
| 367 | ; Set sizes of bss and symbols areas
|
|---|
| 368 | ;
|
|---|
| 369 | MOV EAX, HDR_A.A_BSS_SIZE
|
|---|
| 370 | MOV [DI].P_BSS_SIZE, EAX
|
|---|
| 371 | MOV EAX, HDR_A.A_DRSIZE
|
|---|
| 372 | ADD EAX, HDR_A.A_TRSIZE
|
|---|
| 373 | MOV [DI].P_RELOC_SIZE, EAX
|
|---|
| 374 | MOV EAX, HDR_A.A_SYM_SIZE
|
|---|
| 375 | MOV SYM_SIZE, EAX
|
|---|
| 376 | MOV STR_SIZE, 0
|
|---|
| 377 | ;
|
|---|
| 378 | ; ...
|
|---|
| 379 | ;
|
|---|
| 380 | MOV [DI].P_LAST_PAGE, 0
|
|---|
| 381 | OR EAX, EAX
|
|---|
| 382 | JZ SHORT LL_29
|
|---|
| 383 | CMP STEP_FLAG, FALSE
|
|---|
| 384 | JE SHORT LL_29
|
|---|
| 385 | MOV EDX, [DI].P_SYM_PAGE
|
|---|
| 386 | SHL EDX, 12
|
|---|
| 387 | ADD EDX, [DI].P_EXEC_OFFSET
|
|---|
| 388 | ADD EDX, [DI].P_RELOC_SIZE
|
|---|
| 389 | ADD EDX, EAX ; EAX=SYM_SIZE
|
|---|
| 390 | CALL SEEK
|
|---|
| 391 | JC INVALID_PROG
|
|---|
| 392 | PUSH ECX
|
|---|
| 393 | LEA EDX, STR_SIZE
|
|---|
| 394 | MOV AX, DS
|
|---|
| 395 | MOV ECX, 4
|
|---|
| 396 | CALL READ
|
|---|
| 397 | POP ECX
|
|---|
| 398 | JC READ_ERROR
|
|---|
| 399 | JNZ INVALID_PROG
|
|---|
| 400 | MOV EAX, SYM_SIZE
|
|---|
| 401 | ADD EAX, STR_SIZE
|
|---|
| 402 | MOV EDX, EAX
|
|---|
| 403 | ADD EAX, 0FFFH
|
|---|
| 404 | SHR EAX, 12
|
|---|
| 405 | ADD EAX, [DI].P_SYM_PAGE
|
|---|
| 406 | DEC EAX ; Number of last page
|
|---|
| 407 | AND EDX, 0FFFH ; Complete page?
|
|---|
| 408 | JZ SHORT LL_29 ; Yes -> skip
|
|---|
| 409 | MOV [DI].P_LAST_PAGE, EAX ; Special handling of
|
|---|
| 410 | MOV [DI].P_LAST_BYTES, DX ; last page
|
|---|
| 411 | LL_29: XOR AX, AX ; No error
|
|---|
| 412 | RET
|
|---|
| 413 | ASSUME DI:NOTHING
|
|---|
| 414 | L_LAYOUT ENDP
|
|---|
| 415 |
|
|---|
| 416 |
|
|---|
| 417 | ;
|
|---|
| 418 | ; Prepare page tables for virtual memory
|
|---|
| 419 | ;
|
|---|
| 420 | ASSUME DI:PTR PROCESS
|
|---|
| 421 | L_VMEM PROC NEAR
|
|---|
| 422 | ;
|
|---|
| 423 | ; Check parameters
|
|---|
| 424 | ;
|
|---|
| 425 | TEST [DI].P_STACK_SIZE, 0FFFH
|
|---|
| 426 | JNZ INVALID_PROG
|
|---|
| 427 | TEST [DI].P_STACK_ADDR, 0FFFH
|
|---|
| 428 | JNZ INVALID_PROG
|
|---|
| 429 | TEST [DI].P_TEXT_OFF, 0FFFH
|
|---|
| 430 | JNZ INVALID_PROG
|
|---|
| 431 | TEST [DI].P_DATA_OFF, 0FFFH
|
|---|
| 432 | JNZ INVALID_PROG
|
|---|
| 433 | MOV EAX, [DI].P_TEXT_OFF
|
|---|
| 434 | MOV ECX, [DI].P_TEXT_SIZE
|
|---|
| 435 | ADD EAX, ECX
|
|---|
| 436 | ADD EAX, 0FFFH
|
|---|
| 437 | AND EAX, NOT 0FFFH
|
|---|
| 438 | CMP EAX, [DI].P_DATA_OFF
|
|---|
| 439 | JA INVALID_PROG
|
|---|
| 440 | ;
|
|---|
| 441 | ; Allocate linear address space and initialize page tables
|
|---|
| 442 | ;
|
|---|
| 443 | MOV EAX, [DI].P_DSEG_SIZE ; Add 1.5 MB for __memaccess
|
|---|
| 444 | ADD EAX, 180000H ; and ADD_PAGES
|
|---|
| 445 | MOV [DI].P_LIN_SIZE, EAX
|
|---|
| 446 | ADD EAX, [DI].P_DATA_OFF
|
|---|
| 447 | MOV ECX, EAX ; Combined size
|
|---|
| 448 | MOV AL, [DI].P_PIDX ; Get process index
|
|---|
| 449 | CALL ALLOC_PAGES
|
|---|
| 450 | MOV [DI].P_LINEAR, EAX
|
|---|
| 451 | CALL INIT_PAGES
|
|---|
| 452 | JC OUT_OF_MEM
|
|---|
| 453 | ;
|
|---|
| 454 | ; SRC_EXEC pages (code)
|
|---|
| 455 | ;
|
|---|
| 456 | MOV EAX, [DI].P_TEXT_OFF
|
|---|
| 457 | ADD EAX, [DI].P_LINEAR
|
|---|
| 458 | MOV ECX, [DI].P_TEXT_SIZE
|
|---|
| 459 | ADD ECX, 0FFFH
|
|---|
| 460 | SHR ECX, 12
|
|---|
| 461 | MOV EBX, PAGE_USER ; Page table entry
|
|---|
| 462 | MOV EDX, TEXT_PAGE
|
|---|
| 463 | SHL EDX, 12
|
|---|
| 464 | OR EDX, SRC_EXEC ; Swap table entry
|
|---|
| 465 | MOV DL, [DI].P_PIDX ; PIDX
|
|---|
| 466 | CALL SET_PAGES
|
|---|
| 467 | MOV EBX, [DI].P_LINEAR
|
|---|
| 468 | MOV ECX, [DI].P_TEXT_OFF
|
|---|
| 469 | ADD ECX, [DI].P_TEXT_SIZE
|
|---|
| 470 | TEST [DI].P_HW_ACCESS, HW_ACCESS_CODE ; Data executable?
|
|---|
| 471 | JZ SHORT TEXT_EXEC ; No -> restrict CS to .text
|
|---|
| 472 | MOV ECX, [DI].P_DSEG_SIZE ; Big code segment, with stack
|
|---|
| 473 | TEXT_EXEC: MOV SI, [DI].P_LDT_PTR
|
|---|
| 474 | ADD SI, L_CODE_SEL AND NOT 07H
|
|---|
| 475 | MOV AX, A_CODE32 OR DPL_3
|
|---|
| 476 | CALL CREATE_SEG
|
|---|
| 477 |
|
|---|
| 478 | MOV ECX, [DI].P_DSEG_SIZE
|
|---|
| 479 | MOV EAX, [DI].P_LINEAR
|
|---|
| 480 | ADD EAX, [DI].P_DATA_OFF
|
|---|
| 481 | SUB ECX, [DI].P_DATA_OFF
|
|---|
| 482 | ADD ECX, 0FFFH
|
|---|
| 483 | SHR ECX, 12
|
|---|
| 484 | MOV EBX, 000H ; Page table entry
|
|---|
| 485 | MOV EDX, 000H ; Swap table entry
|
|---|
| 486 | CALL SET_PAGES ; Inaccessible
|
|---|
| 487 |
|
|---|
| 488 | ;
|
|---|
| 489 | ; SRC_NONE pages (stack)
|
|---|
| 490 | ;
|
|---|
| 491 | MOV EAX, [DI].P_STACK_ADDR
|
|---|
| 492 | ADD EAX, [DI].P_LINEAR
|
|---|
| 493 | MOV ECX, [DI].P_STACK_SIZE
|
|---|
| 494 | SUB EAX, ECX
|
|---|
| 495 | SHR ECX, 12
|
|---|
| 496 | MOV EBX, PAGE_WRITE OR PAGE_USER
|
|---|
| 497 | MOV EDX, SRC_NONE ; SRC
|
|---|
| 498 | TEST [DI].P_FLAGS, PF_DONT_ZERO
|
|---|
| 499 | JNZ SHORT LV_04
|
|---|
| 500 | MOV EDX, SRC_ZERO ; Swap table entry
|
|---|
| 501 | LV_04: MOV DL, [DI].P_PIDX ; PIDX
|
|---|
| 502 | CALL SET_PAGES ; Stack
|
|---|
| 503 | ;
|
|---|
| 504 | ; Commit stack pages
|
|---|
| 505 | ;
|
|---|
| 506 | TEST [DI].P_FLAGS, PF_COMMIT
|
|---|
| 507 | JZ SHORT LV_09
|
|---|
| 508 | MOV ECX, [DI].P_COMMIT_SIZE
|
|---|
| 509 | ADD ECX, 4*4096
|
|---|
| 510 | CMP ECX, [DI].P_STACK_SIZE
|
|---|
| 511 | JB SHORT LV_05
|
|---|
| 512 | MOV ECX, [DI].P_STACK_SIZE
|
|---|
| 513 | LV_05: MOV EAX, [DI].P_STACK_ADDR
|
|---|
| 514 | ADD EAX, [DI].P_LINEAR
|
|---|
| 515 | SUB EAX, ECX
|
|---|
| 516 | SHR ECX, 12
|
|---|
| 517 | CALL SET_COMMIT ; Set PAGE_ALLOC bit
|
|---|
| 518 | CALL SET_PAGES
|
|---|
| 519 | JC OUT_OF_MEM
|
|---|
| 520 | LV_09:
|
|---|
| 521 | ;
|
|---|
| 522 | ; SRC_ZERO pages (bss)
|
|---|
| 523 | ;
|
|---|
| 524 | MOV EAX, [DI].P_BSS_OFF
|
|---|
| 525 | ADD EAX, [DI].P_LINEAR
|
|---|
| 526 | MOV ECX, [DI].P_BSS_SIZE
|
|---|
| 527 | JECXZ LV_11
|
|---|
| 528 | ADD ECX, EAX
|
|---|
| 529 | DEC ECX
|
|---|
| 530 | SHR ECX, 12 ; Last bss page
|
|---|
| 531 | MOV EDX, EAX
|
|---|
| 532 | SHR EDX, 12 ; First bss page
|
|---|
| 533 | SUB ECX, EDX
|
|---|
| 534 | INC ECX
|
|---|
| 535 | MOV EBX, PAGE_WRITE OR PAGE_USER ; Page table entry
|
|---|
| 536 | MOV EDX, SRC_ZERO ; Swap table entry
|
|---|
| 537 | MOV DL, [DI].P_PIDX ; PIDX
|
|---|
| 538 | CALL SET_COMMIT ; Set PAGE_ALLOC bit
|
|---|
| 539 | CALL SET_PAGES ; Stack
|
|---|
| 540 | JC OUT_OF_MEM ; ...deallocate memory
|
|---|
| 541 | LV_11:
|
|---|
| 542 |
|
|---|
| 543 | ;
|
|---|
| 544 | ; SRC_EXEC pages (data)
|
|---|
| 545 | ;
|
|---|
| 546 | MOV EAX, [DI].P_DATA_OFF
|
|---|
| 547 | ADD EAX, [DI].P_LINEAR
|
|---|
| 548 | MOV ECX, [DI].P_DATA_SIZE
|
|---|
| 549 | ADD ECX, 0FFFH
|
|---|
| 550 | SHR ECX, 12
|
|---|
| 551 | MOV EBX, PAGE_WRITE OR PAGE_USER
|
|---|
| 552 | MOV EDX, DATA_PAGE
|
|---|
| 553 | SHL EDX, 12
|
|---|
| 554 | OR EDX, SRC_EXEC
|
|---|
| 555 | MOV DL, [DI].P_PIDX ; PIDX
|
|---|
| 556 | CALL SET_COMMIT ; Set PAGE_ALLOC bit
|
|---|
| 557 | CALL SET_PAGES
|
|---|
| 558 | JC OUT_OF_MEM ; ...deallocate memory
|
|---|
| 559 |
|
|---|
| 560 | MOV EBX, [DI].P_LINEAR
|
|---|
| 561 | MOV ECX, [DI].P_DSEG_SIZE
|
|---|
| 562 | MOV SI, [DI].P_LDT_PTR
|
|---|
| 563 | ADD SI, L_DATA_SEL AND NOT 07H
|
|---|
| 564 | MOV AX, A_DATA32 OR DPL_3
|
|---|
| 565 | CALL CREATE_SEG
|
|---|
| 566 | CALL CLEAR_TLB
|
|---|
| 567 | XOR AX, AX
|
|---|
| 568 | RET
|
|---|
| 569 | ASSUME DI:NOTHING
|
|---|
| 570 | L_VMEM ENDP
|
|---|
| 571 |
|
|---|
| 572 | ;
|
|---|
| 573 | ; Load symbols
|
|---|
| 574 | ;
|
|---|
| 575 | ASSUME DI:PTR PROCESS
|
|---|
| 576 | L_SYMBOLS PROC NEAR
|
|---|
| 577 | CMP STEP_FLAG, FALSE ; Debugging?
|
|---|
| 578 | JE SHORT L_SYMBOLS_RET ; No -> done
|
|---|
| 579 | MOV EAX, SYM_SIZE
|
|---|
| 580 | OR EAX, EAX
|
|---|
| 581 | JZ SHORT L_SYMBOLS_RET
|
|---|
| 582 | MOV [DI].P_STR_OFF, EAX
|
|---|
| 583 | XOR EDX, EDX
|
|---|
| 584 | MOV EBX, SIZE NLIST
|
|---|
| 585 | DIV EBX
|
|---|
| 586 | MOV [DI].P_SYMBOLS, EAX
|
|---|
| 587 | MOV ECX, SYM_SIZE
|
|---|
| 588 | ADD ECX, STR_SIZE
|
|---|
| 589 | MOV AL, [DI].P_PIDX ; Get process index
|
|---|
| 590 | CALL ALLOC_PAGES
|
|---|
| 591 | CALL INIT_PAGES
|
|---|
| 592 | JC OUT_OF_MEM
|
|---|
| 593 | MOV EBX, PAGE_USER ; Read only
|
|---|
| 594 | MOV EDX, [DI].P_SYM_PAGE
|
|---|
| 595 | SHL EDX, 12
|
|---|
| 596 | OR EDX, SRC_EXEC ; SRC
|
|---|
| 597 | MOV DL, [DI].P_PIDX ; PIDX
|
|---|
| 598 | CALL SET_PAGES
|
|---|
| 599 | MOV ECX, SYM_SIZE
|
|---|
| 600 | ADD ECX, STR_SIZE
|
|---|
| 601 | MOV EBX, EAX
|
|---|
| 602 | MOV SI, [DI].P_LDT_PTR
|
|---|
| 603 | ADD SI, L_SYM_SEL AND NOT 07H
|
|---|
| 604 | MOV AX, A_READ32 OR DPL_3
|
|---|
| 605 | CALL CREATE_SEG
|
|---|
| 606 | CALL CLEAR_TLB
|
|---|
| 607 | L_SYMBOLS_RET: XOR AX, AX
|
|---|
| 608 | RET
|
|---|
| 609 | ASSUME DI:NOTHING
|
|---|
| 610 | L_SYMBOLS ENDP
|
|---|
| 611 |
|
|---|
| 612 |
|
|---|
| 613 | ;
|
|---|
| 614 | ; Preload code and initialized data
|
|---|
| 615 | ;
|
|---|
| 616 | ASSUME DI:PTR PROCESS
|
|---|
| 617 | L_PRELOAD PROC NEAR
|
|---|
| 618 | TEST [DI].P_FLAGS, PF_PRELOAD; Preloading disabled?
|
|---|
| 619 | JNZ L_PRELOAD_RET ; Yes -> return
|
|---|
| 620 | CALL PM_AVAIL ; Number of available pages
|
|---|
| 621 | MOV EDX, EAX ; of memory
|
|---|
| 622 | MOV EAX, [DI].P_DATA_OFF
|
|---|
| 623 | ADD EAX, [DI].P_DATA_SIZE
|
|---|
| 624 | ADD EAX, 0FFFH ; Number of pages required
|
|---|
| 625 | SHR EAX, 12
|
|---|
| 626 | CMP EAX, EDX ; Enough memory?
|
|---|
| 627 | JA L_PRELOAD_RET ; No -> don't preload
|
|---|
| 628 | OR [DI].P_FLAGS, PF_PRELOADING ; Preloading...
|
|---|
| 629 | MOV BX, [DI].P_EXEC_HANDLE ; Get file handle
|
|---|
| 630 | .386P
|
|---|
| 631 | SLDT AX
|
|---|
| 632 | PUSH AX ; Save LDTR
|
|---|
| 633 | LLDT [DI].P_LDT ; Switch to new process
|
|---|
| 634 | .386
|
|---|
| 635 | ;
|
|---|
| 636 | ; Preload code
|
|---|
| 637 | ;
|
|---|
| 638 | MOV EDX, TEXT_PAGE
|
|---|
| 639 | SHL EDX, 12
|
|---|
| 640 | ADD EDX, [DI].P_EXEC_OFFSET ; Get location of image
|
|---|
| 641 | CALL SEEK ; Seek to code segment
|
|---|
| 642 | JC SHORT L_PRELOAD_ERR
|
|---|
| 643 | MOV ECX, [DI].P_TEXT_SIZE ; Size of code
|
|---|
| 644 | MOV EDX, [DI].P_TEXT_OFF ; Destination address
|
|---|
| 645 | MOV AX, L_DATA_SEL
|
|---|
| 646 | CALL READ ; Read image
|
|---|
| 647 | JC SHORT L_PRELOAD_ERR
|
|---|
| 648 | JNZ SHORT L_PRELOAD_ERR
|
|---|
| 649 | MOV EAX, [DI].P_TEXT_OFF
|
|---|
| 650 | ADD EAX, [DI].P_LINEAR
|
|---|
| 651 | MOV ECX, [DI].P_TEXT_SIZE
|
|---|
| 652 | ADD ECX, 0FFFH
|
|---|
| 653 | SHR ECX, 12
|
|---|
| 654 | CALL CLEAR_DIRTY
|
|---|
| 655 | ;
|
|---|
| 656 | ; Preload data
|
|---|
| 657 | ;
|
|---|
| 658 | MOV EDX, DATA_PAGE
|
|---|
| 659 | SHL EDX, 12
|
|---|
| 660 | ADD EDX, [DI].P_EXEC_OFFSET ; Get location of image
|
|---|
| 661 | CALL SEEK ; Seek to data segment
|
|---|
| 662 | JC SHORT L_PRELOAD_ERR
|
|---|
| 663 | MOV ECX, [DI].P_DATA_SIZE ; Size of data
|
|---|
| 664 | MOV EDX, [DI].P_DATA_OFF ; Destination address
|
|---|
| 665 | MOV AX, L_DATA_SEL
|
|---|
| 666 | CALL READ ; Read image
|
|---|
| 667 | JC SHORT L_PRELOAD_ERR
|
|---|
| 668 | JNZ SHORT L_PRELOAD_ERR
|
|---|
| 669 | MOV EAX, [DI].P_DATA_OFF
|
|---|
| 670 | ADD EAX, [DI].P_LINEAR
|
|---|
| 671 | MOV ECX, [DI].P_DATA_SIZE
|
|---|
| 672 | ADD ECX, 0FFFH
|
|---|
| 673 | SHR ECX, 12
|
|---|
| 674 | CALL CLEAR_DIRTY
|
|---|
| 675 | XOR AX, AX ; NC, ZR
|
|---|
| 676 | L_PRELOAD_ERR: POP AX
|
|---|
| 677 | .386P
|
|---|
| 678 | LLDT AX ; Restore LDT
|
|---|
| 679 | .386
|
|---|
| 680 | JC SHORT READ_ERROR
|
|---|
| 681 | JNZ SHORT INVALID_PROG
|
|---|
| 682 | AND [DI].P_FLAGS, NOT PF_PRELOADING ; End of preloading
|
|---|
| 683 | L_PRELOAD_RET: XOR AX, AX ; No error
|
|---|
| 684 | RET
|
|---|
| 685 | ASSUME DI:NOTHING
|
|---|
| 686 | L_PRELOAD ENDP
|
|---|
| 687 |
|
|---|
| 688 |
|
|---|
| 689 | READ_ERROR:: MOV AX, ENOEXEC
|
|---|
| 690 | LEA EDX, $CANT_READ
|
|---|
| 691 | RET
|
|---|
| 692 |
|
|---|
| 693 | INVALID_PROG:: MOV AX, ENOEXEC
|
|---|
| 694 | LEA EDX, $INVALID_PROG
|
|---|
| 695 | RET
|
|---|
| 696 |
|
|---|
| 697 | INVALID_VERSION::
|
|---|
| 698 | MOV AX, ENOEXEC
|
|---|
| 699 | LEA EDX, $INVALID_VER
|
|---|
| 700 | RET
|
|---|
| 701 |
|
|---|
| 702 | OUT_OF_MEM:: MOV AX, ENOMEM
|
|---|
| 703 | LEA EDX, $LOADER_MEM
|
|---|
| 704 | RET
|
|---|
| 705 |
|
|---|
| 706 | LOADER ENDP
|
|---|
| 707 |
|
|---|
| 708 |
|
|---|
| 709 | SV_CODE ENDS
|
|---|
| 710 |
|
|---|
| 711 | END
|
|---|