Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

566 lines
11 KiB

  1. TITLE LDSELF - BootStrap procedure for KERNEL.EXE
  2. .xlist
  3. ?NODATA=1
  4. ?TF=1
  5. include kernel.inc
  6. include newexe.inc
  7. include tdb.inc
  8. .list
  9. externFP IGlobalAlloc
  10. externFP IGlobalLock
  11. externFP IGlobalUnlock
  12. DataBegin
  13. externW winVer
  14. ;externW pGlobalHeap
  15. DataEnd
  16. sBegin CODE
  17. assumes CS,CODE
  18. assumes DS,NOTHING
  19. assumes ES,NOTHING
  20. ;externW MyCSDS
  21. externNP SetOwner
  22. externFP set_discarded_sel_owner
  23. ; extra debugging parameter for EntProcAddress to avoid RIPing if all
  24. ; we are doing is a GetProcAddress to something that isn't there.
  25. externNP EntProcAddress
  26. cProc FarEntProcAddress,<PUBLIC,FAR,NODATA>
  27. parmW hExe
  28. parmW entno
  29. cBegin
  30. if KDEBUG
  31. mov cx,1
  32. cCall EntProcAddress,<hExe,entno,cx>
  33. else
  34. cCall EntProcAddress,<hExe,entno>
  35. endif
  36. cEnd
  37. if KDEBUG
  38. ; AppLoaderEntProcAddress
  39. ; This call added for the app loader. The above call (FarEntProcAddress)
  40. ; forces no RIPs. When we're using the app loader, we really want
  41. ; RIPs, so in debug we add this entry point.
  42. ; This call ONLY exists in debug.
  43. cProc AppLoaderEntProcAddress,<PUBLIC,FAR,NODATA>
  44. parmW hExe
  45. parmW entno
  46. cBegin
  47. xor cx,cx ;Force RIPs on this one
  48. cCall EntProcAddress,<hExe,entno,cx>
  49. cEnd
  50. endif ; KDEBUG
  51. externNP FindOrdinal
  52. cProc FarFindOrdinal,<PUBLIC,FAR,NODATA>
  53. parmW hExe
  54. parmD lpname
  55. parmW fh
  56. cBegin
  57. cCall FindOrdinal,<hExe,lpName,fh>
  58. cEnd
  59. externNP LoadSegment
  60. cProc FarLoadSegment,<PUBLIC,FAR,NODATA>
  61. parmW hExe
  62. parmW segno
  63. parmW fh
  64. parmW isfh
  65. cBegin
  66. cCall LoadSegment,<hExe,segno,fh,isfh>
  67. cEnd
  68. externNP AllocSeg
  69. cProc FarAllocSeg,<PUBLIC,FAR,NODATA>
  70. parmD pSegInfo
  71. cBegin
  72. cCall AllocSeg,<pSegInfo>
  73. cEnd
  74. externNP DeleteTask
  75. cProc FarDeleteTask,<PUBLIC,FAR,NODATA,ATOMIC>
  76. parmW taskID
  77. cBegin
  78. cCall DeleteTask,<taskID>
  79. cEnd
  80. externNP UnlinkObject
  81. cProc FarUnlinkObject,<PUBLIC,FAR,NODATA,ATOMIC>
  82. cBegin
  83. cCall UnlinkObject
  84. cEnd
  85. externNP MyLower
  86. cProc FarMyLower,<PUBLIC,FAR,NODATA,ATOMIC>
  87. cBegin
  88. cCall MyLower
  89. cEnd
  90. externNP MyUpper
  91. cProc FarMyUpper,<PUBLIC,FAR,NODATA,ATOMIC>
  92. cBegin
  93. cCall MyUpper
  94. cEnd
  95. externNP MyAlloc
  96. cProc FarMyAlloc,<PUBLIC,FAR,NODATA>
  97. parmW aflags
  98. parmW nsize
  99. parmW nelem
  100. cBegin
  101. cCall MyAlloc,<aflags,nsize,nelem>
  102. cEnd
  103. externNP MyAllocLinear
  104. cProc FarMyAllocLinear,<PUBLIC,FAR,NODATA>
  105. parmW aflags
  106. parmD dwBytes
  107. cBegin
  108. cCall MyAllocLinear,<aflags,dwBytes>
  109. cEnd
  110. externNP MyLock
  111. cProc FarMyLock,<PUBLIC,FAR,NODATA>
  112. parmW h1
  113. cBegin
  114. cCall MyLock,<h1>
  115. cEnd
  116. externNP MyFree
  117. cProc FarMyFree,<PUBLIC,FAR,NODATA>
  118. parmW h2
  119. cBegin
  120. cCall MyFree,<h2>
  121. cEnd
  122. externNP genter
  123. cProc Far_genter,<PUBLIC,FAR,NODATA,ATOMIC>
  124. cBegin
  125. cCall genter
  126. cEnd
  127. externNP gleave
  128. cProc Far_gleave,<PUBLIC,FAR,NODATA,ATOMIC>
  129. cBegin
  130. cCall gleave
  131. cEnd
  132. externNP lalign
  133. cProc Far_lalign,<PUBLIC,FAR,NODATA,ATOMIC>
  134. cBegin
  135. cCall lalign
  136. cEnd
  137. externNP lrepsetup
  138. cProc Far_lrepsetup,<PUBLIC,FAR,NODATA,ATOMIC>
  139. cBegin
  140. cCall lrepsetup
  141. cEnd
  142. if KDEBUG
  143. externNP lfillCC
  144. cProc Far_lfillCC,<PUBLIC,FAR,NODATA,ATOMIC>
  145. cBegin
  146. cCall lfillCC
  147. cEnd
  148. endif
  149. sEnd CODE
  150. sBegin INITCODE
  151. ;-----------------------------------------------------------------------;
  152. ; LKExeHeader ;
  153. ; ;
  154. ; Copy of LoadExeHeader (from LDHEADER.ASM) that has been stripped ;
  155. ; down to the minimum needed to load the new format .EXE header for ;
  156. ; KERNEL.EXE. ;
  157. ; ;
  158. ; Arguments: ;
  159. ; parmW pMem ;
  160. ; parmD pfilename ;
  161. ; ;
  162. ; Returns: ;
  163. ; AX = segment of exe header ;
  164. ; ;
  165. ; Error Returns: ;
  166. ; AX = 0 ;
  167. ; ;
  168. ; Registers Preserved: ;
  169. ; DI,SI,DS ;
  170. ; ;
  171. ; Registers Destroyed: ;
  172. ; AX,BX,CX,DX,ES ;
  173. ; Calls: ;
  174. ; ;
  175. ; History: ;
  176. ; ;
  177. ; Thu Mar 19, 1987 08:35:32p -by- David N. Weise [davidw] ;
  178. ; Added this nifty comment block. ;
  179. ;-----------------------------------------------------------------------;
  180. cProc LKExeHeader,<PUBLIC,NEAR>,<si,di,ds>
  181. parmW pMem
  182. parmD pfilename
  183. localW nchars
  184. cBegin
  185. lds si,pfilename
  186. xor ax,ax
  187. mov al,ds:[si].opLen
  188. inc ax ; include null byte
  189. mov nchars,ax
  190. mov ds,pMem
  191. xor si,si
  192. mov di,ds:[si].ne_enttab ; Compute size of resident new header
  193. add di, 6 ; Room for one block of entries
  194. push si
  195. mov si, ds:[si].ne_enttab ; Scan current entry table
  196. calc_next_block:
  197. lodsw
  198. xor cx, cx
  199. mov cl, al
  200. jcxz calc_ent_sized
  201. cmp ah, ENT_UNUSED ; 6 bytes per unused block
  202. jne calc_used_block
  203. add di, 6
  204. jmps calc_next_block
  205. calc_used_block:
  206. errnz <5-SIZE PENT>
  207. mov bx, cx
  208. shl bx, 1
  209. add di, bx
  210. add di, bx ; 5 bytes per entry
  211. add di, cx
  212. add si, bx
  213. add si, cx ; Skip the block
  214. cmp ah, ENT_MOVEABLE
  215. jne calc_next_block
  216. calc_moveable_block:
  217. add si, bx
  218. add si, cx ; Skip the block
  219. jmps calc_next_block
  220. calc_ent_sized:
  221. pop si
  222. mov cx,ds:[si].ne_cseg ; + 3 * #segments
  223. ; Reserve space for segment reference bytes
  224. add di,cx
  225. shl cx,1
  226. ; Reserve space for ns_handle field in segment table
  227. add di,cx
  228. errnz <10-SIZE NEW_SEG1>
  229. if LDCHKSUM
  230. ; Reserve space for segment chksum table (2 words per segment)
  231. add di,cx
  232. add di,cx
  233. endif
  234. ; Reserve space for file info block at end
  235. add di,16 ; 16 bytes of slop
  236. add di,nchars ; + size of file info block
  237. xor ax,ax ; Allocate a block for header
  238. cCall IGlobalAlloc,<GA_MOVEABLE,ax,di>
  239. push ax
  240. cCall IGlobalLock,<ax>
  241. pop ax
  242. push dx
  243. cCall IGlobalUnlock,<ax>
  244. pop ax
  245. mov es,ax ; ES:DI -> new header location
  246. xor di,di
  247. cld ; DS:SI -> old header
  248. mov cx,SIZE NEW_EXE ; Copy fixed portion of header
  249. cld
  250. rep movsb
  251. mov cx,es:[ne_cseg] ; Copy segment table
  252. mov es:[ne_segtab],di
  253. recopyseg:
  254. if ROM
  255. ; This code assumes kernel segments will not need to be reloaded from ROM
  256. ; and so doesn't set the ns_sector field like LoadExeHeader().
  257. lodsw ; ns_sector has segment selector in ROM
  258. mov bx,ax
  259. stosw
  260. else
  261. movsw ; ns_sector
  262. endif
  263. movsw ; ns_cbseg
  264. lodsw ; ns_flags
  265. errnz <4-ns_flags>
  266. and ax,not NS286DOS ; Clear 286DOS bits
  267. if ROM
  268. or ax,NENOTP+4000h+NSINROM+NSLOADED ; library code in ROM
  269. else
  270. or ax,NENOTP+4000h ; Mark library code segments
  271. endif
  272. stosw
  273. movsw ; ns_minalloc
  274. errnz <8-SIZE NEW_SEG>
  275. if ROM
  276. mov ax,bx
  277. else
  278. xor ax,ax
  279. endif
  280. stosw ; one word for ns_handle field
  281. errnz <10-SIZE NEW_SEG1>
  282. loop recopyseg
  283. recopysegx:
  284. mov cx,es:[ne_restab] ; Copy resource table
  285. sub cx,es:[ne_rsrctab]
  286. mov es:[ne_rsrctab],di
  287. rep movsb
  288. rerestab:
  289. mov cx,es:[ne_modtab] ; Copy resident name table
  290. sub cx,es:[ne_restab]
  291. mov es:[ne_restab],di
  292. rep movsb
  293. mov cx,es:[ne_imptab] ; Copy module xref table
  294. sub cx,es:[ne_modtab]
  295. mov es:[ne_modtab],di
  296. rep movsb
  297. mov es:[ne_psegrefbytes],di ; Insert segment reference byte table
  298. mov cx,es:[ne_cseg]
  299. mov al,0FFh
  300. rep stosb ; initialize to not-loaded condition
  301. mov es:[ne_pretthunks],di ; Setup return thunks
  302. if LDCHKSUM
  303. mov es:[ne_psegcsum],di ; Setup segment chksum table
  304. mov cx,es:[ne_cseg]
  305. jcxz resetsegcsumexit
  306. xor ax,ax
  307. shl cx,1 ; Two words per segment
  308. rep stosw
  309. resetsegcsumexit:
  310. endif
  311. mov cx,es:[ne_enttab] ; Copy imported name table
  312. sub cx,es:[ne_imptab]
  313. mov es:[ne_imptab],di
  314. jcxz reenttab
  315. rep movsb
  316. reenttab:
  317. mov es:[ne_enttab],di
  318. ; Scan current entry table
  319. xor ax, ax ; First entry in block
  320. mov bx, di ; Pointer to info for this block
  321. stosw ; Starts at 0
  322. stosw ; Ends at 0
  323. stosw ; And is not even here!
  324. copy_next_block:
  325. lodsw ; Get # entries and type
  326. xor cx, cx
  327. mov cl, al
  328. jcxz copy_ent_done
  329. mov al, ah
  330. cmp al, ENT_UNUSED
  331. jne copy_used_block
  332. mov ax, es:[bx].PM_EntEnd ; Last entry in current block
  333. cmp ax, es:[bx].PM_EntStart ; No current block?
  334. jne end_used_block
  335. int 3
  336. add es:[bx].PM_EntStart, cx
  337. add es:[bx].PM_EntEnd, cx
  338. jmps copy_next_block
  339. end_used_block:
  340. mov es:[bx].PM_EntNext, di ; Pointer to next block
  341. mov bx, di
  342. add ax, cx ; Skip unused entries
  343. stosw ; First in new block
  344. stosw ; Last in new block
  345. xor ax, ax
  346. stosw ; End of list
  347. jmps copy_next_block
  348. copy_used_block:
  349. add es:[bx].PM_EntEnd, cx ; Add entries in this block
  350. cmp al, ENT_MOVEABLE
  351. je copy_moveable_block
  352. copy_fixed_block:
  353. stosb ; Segno
  354. movsb ; Flag byte
  355. stosb ; segno again to match structure
  356. movsw ; Offset
  357. loop copy_fixed_block
  358. jmps copy_next_block
  359. copy_moveable_block:
  360. stosb ; ENT_MOVEABLE
  361. movsb ; Flag byte
  362. add si, 2 ; Toss int 3Fh
  363. movsb ; Copy segment #
  364. movsw ; and offset
  365. loop copy_moveable_block
  366. jmps copy_next_block
  367. copy_ent_done:
  368. xor bx,bx
  369. mov es:[bx].ne_usage,1
  370. mov es:[bx].ne_pnextexe,bx
  371. mov es:[bx].ne_pautodata,bx
  372. mov cx,nchars
  373. mov es:[bx].ne_pfileinfo,di
  374. lds si,pfilename
  375. rep movsb
  376. SetKernelDS
  377. mov ax,winVer
  378. mov es:[bx].ne_expver,ax
  379. if ROM
  380. or es:[bx].ne_flags,NENONRES OR NEMODINROM ;have disc code & in ROM
  381. else
  382. or es:[bx].ne_flags,NENONRES ; Remember that we have
  383. ; discardable code
  384. endif
  385. UnSetKernelDS
  386. cCall SetOwner,<es,es>
  387. mov ax,es
  388. reexit:
  389. cEnd
  390. ife ROM ;----------------------------------------------------------------
  391. cProc LKAllocSegs,<PUBLIC,NEAR>,<si,di,ds>
  392. parmW hExe
  393. localW fixed_seg
  394. localW SegCount
  395. cBegin
  396. mov ds,hExe
  397. mov si,ds:[ne_segtab]
  398. mov di,ds:[si].ns_minalloc
  399. xor ax,ax
  400. mov bx,(GA_ALLOC_LOW or GA_CODE_DATA) shl 8
  401. cCall IGlobalAlloc,<bx,ax,di>
  402. or ax,ax
  403. jz lkallocfail
  404. mov fixed_seg,ax
  405. mov ds:[si].ns_handle,ax
  406. and byte ptr ds:[si].ns_flags,not NSLOADED
  407. or byte ptr ds:[si].ns_flags,NSALLOCED
  408. cCall SetOwner,<ax,ds>
  409. add si,SIZE NEW_SEG1 ; NRES segment
  410. mov di,ds:[si].ns_sector
  411. mov SegCount, 0 ; NRES and MISC segments
  412. ;; SetKernelDS es
  413. ;; cmp fWinX,0
  414. ;; UnSetKernelDS es
  415. ;; je lk1
  416. ;; mov di,ds:[si].ns_cbseg
  417. ;; xchg ds:[si].ns_minalloc,di
  418. ;; xchg ds:[si].ns_sector,di
  419. ;;lk1:
  420. SegLoop:
  421. inc SegCount
  422. xor ax,ax
  423. mov bh,GA_DISCARDABLE + GA_SHAREABLE + GA_CODE_DATA
  424. mov bl,GA_MOVEABLE + GA_DISCCODE
  425. cCall IGlobalAlloc,<bx,ax,ax>
  426. or ax,ax
  427. jz lkallocfail
  428. mov ds:[si].ns_handle,ax ; Handle into seg table
  429. and byte ptr ds:[si].ns_flags,not NSLOADED
  430. or byte ptr ds:[si].ns_flags,NSALLOCED
  431. mov bx,ax ; put handle into base register
  432. smov es,ds
  433. call set_discarded_sel_owner
  434. smov es,0
  435. mov bx,ds:[si].ns_sector ; Save MiscCode sector
  436. add si,SIZE NEW_SEG1 ; Next segment
  437. cmp SegCount, 2
  438. jnz SegLoop
  439. ; Allocate fixed block for kernel's data segment
  440. push bx ; Save MisCode sector
  441. mov bx,ds:[si].ns_minalloc
  442. xor ax,ax
  443. cCall IGlobalAlloc,<ax,ax,bx>
  444. pop bx
  445. or ax,ax
  446. jz lkallocfail
  447. mov ds:[ne_pautodata], si
  448. mov ds:[si].ns_handle,ax
  449. and byte ptr ds:[si].ns_flags,not NSLOADED
  450. or byte ptr ds:[si].ns_flags,NSALLOCED
  451. cCall SetOwner,<ax,ds>
  452. mov ax,di ; Return offset to NR segment
  453. lkallocfail:
  454. cEnd
  455. endif ;ROM ---------------------------------------------------------
  456. nop ; Stop linker from padding segment
  457. sEnd INITCODE
  458. end