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.

1091 lines
31 KiB

  1. DOSSEG
  2. .MODEL LARGE
  3. include disk.inc
  4. include partit.inc
  5. .DATA
  6. extrn _x86BootCode:far
  7. .DATA?
  8. extrn PartitionList:dword
  9. extrn PartitionListCount:word
  10. .CODE
  11. ASSUME ds:NOTHING
  12. extrn _malloc:far
  13. extrn _free:far
  14. extrn _qsort:far
  15. extrn _ReadDisk:far
  16. extrn _WriteDisk:far
  17. extrn _GetDiskInfoByHandle:far
  18. .386
  19. ;++
  20. ;
  21. ; INT
  22. ; _far
  23. ; MakePartitionAtStartOfDisk(
  24. ; IN HDISK DiskHandle,
  25. ; OUT FPVOID SectorBuffer,
  26. ; IN ULONG MinimumSectorCount,
  27. ; IN UINT PartitionClass,
  28. ; IN BYTE SystemId OPTIONAL
  29. ; );
  30. ;
  31. ; Routine Description:
  32. ;
  33. ; This routine makes a new primary partition of at least
  34. ; a given number of sectors. The partition may be larger
  35. ; to keep it aligned on the proper cyl/track boundary.
  36. ;
  37. ; Only int13 disk units are supported.
  38. ;
  39. ; Arguments:
  40. ;
  41. ; DiskHandle - supplies a disk handle as returned by OpenDisk().
  42. ;
  43. ; SectorBuffer - supplies a pointer to a buffer suitable for use
  44. ; for i/o of a single sector. This buffer must not
  45. ; cross a DMA boundary, but the caller is responsible
  46. ; for ensuring this.
  47. ;
  48. ; MinimumSectorCount - supplies the minimum number of sectors
  49. ; that the partition should contain.
  50. ;
  51. ; PartitionClass - supplies a value indicating what class of system id
  52. ; should be used for the partition.
  53. ;
  54. ; PARTCLASS_FAT - creates a type 1, 4, or 6, or e partition
  55. ; depending on size and availability of xint13
  56. ; services for the drive.
  57. ;
  58. ; PARTCLASS_FAT32 - creates a type b or c partition depending
  59. ; on availability of xint13 services for the drive.
  60. ;
  61. ; PARTCLASS_NTFS - creates a type 7 partition.
  62. ;
  63. ; PARTCLASS_OTHER - create a partition whose type is given by
  64. ; the SystemId parameter.
  65. ;
  66. ; SystemId - if PartitionClass is PARTCLASS_OTHER, supplies the
  67. ; system id for the partition. Ignored otherwise.
  68. ;
  69. ; Return Value:
  70. ;
  71. ; Partition id of newly created partition, or -1 if failure.
  72. ;
  73. ;--
  74. DiskHandle equ dword ptr [bp+6]
  75. DiskHandlel equ word ptr [bp+6]
  76. DiskHandleh equ word ptr [bp+8]
  77. SectorBuffer equ dword ptr [bp+10]
  78. SectorBufferl equ word ptr [bp+10]
  79. SectorBufferh equ word ptr [bp+12]
  80. MinimumSectorCount equ dword ptr [bp+14]
  81. MinimumSectorCountl equ word ptr [bp+14]
  82. MinimumSectorCounth equ word ptr [bp+16]
  83. PartitionClass equ word ptr [bp+18]
  84. SystemId equ byte ptr [bp+20]
  85. ExtSecCnth equ word ptr [bp-2]
  86. ExtSecCntl equ word ptr [bp-4]
  87. ExtSecCnt equ dword ptr [bp-4]
  88. Cylinders equ word ptr [bp-6]
  89. Heads equ word ptr [bp-8]
  90. SectorsPerTrack equ byte ptr [bp-9]
  91. Int13UnitNumber equ byte ptr [bp-10]
  92. SectorsPerCylinder equ word ptr [bp-12]
  93. DiskSizeh equ word ptr [bp-14]
  94. DiskSizel equ word ptr [bp-16]
  95. DiskSize equ dword ptr [bp-16]
  96. DiskId equ word ptr [bp-18]
  97. Tableh equ word ptr [bp-20]
  98. Tablel equ word ptr [bp-22]
  99. Table equ dword ptr [bp-22]
  100. FreeStarth equ word ptr [bp-24]
  101. FreeStartl equ word ptr [bp-26]
  102. FreeStart equ dword ptr [bp-26]
  103. START_AND_SIZE STRUC
  104. PartStartl dw ?
  105. PartStarth dw ?
  106. PartSizel dw ?
  107. PartSizeh dw ?
  108. START_AND_SIZE ENDS
  109. public _MakePartitionAtStartOfDisk
  110. _MakePartitionAtStartOfDisk proc far
  111. push bp
  112. mov bp,sp
  113. sub sp,26
  114. push ds
  115. push es
  116. push bx
  117. push si
  118. push di
  119. ;
  120. ; Get disk info. This also makes sure the handle is open,
  121. ; calculates the number of sectors we can address on the disk,
  122. ; and the number of sectors in a cylinder.
  123. ;
  124. call near ptr pGetDiskValues
  125. jnc @f
  126. mov ax,0ffffh
  127. jc done2
  128. ;
  129. ; Allocate a buffer for our table.
  130. ; Make sure ds addresses DGROUP for crt
  131. ;
  132. @@: push ds
  133. push DGROUP
  134. pop ds
  135. push 5 * SIZE START_AND_SIZE
  136. call _malloc
  137. add sp,2
  138. pop ds
  139. mov cx,ax
  140. or cx,dx
  141. jnz @f
  142. dec ax ; ax = -1 for error return
  143. jmp done2
  144. @@: mov Tableh,dx
  145. mov Tablel,ax
  146. ;
  147. ; Read sector 0 of the disk.
  148. ;
  149. push SectorBuffer
  150. push 1
  151. push 0
  152. push 0
  153. push DiskHandle
  154. call _ReadDisk
  155. add sp,14
  156. cmp ax,0
  157. jne @f
  158. dec ax
  159. jmp done1 ; ax = -1 for error exit
  160. ;
  161. ; Make sure the MBR is valid.
  162. ;
  163. @@: lds si,SectorBuffer
  164. cmp word ptr [si+510],0aa55h
  165. je @f
  166. mov ax,0ffffh
  167. jmp done1
  168. ;
  169. ; Zero out the start/offset table.
  170. ;
  171. @@: les di,Table ; es:di -> local start/size table
  172. mov ax,0
  173. mov cx,4*(SIZE START_AND_SIZE)
  174. cld
  175. rep stosb
  176. ;
  177. ; Build the start/offset table.
  178. ;
  179. mov cx,4 ; cx = loop count
  180. add si,1beh ; ds:si -> start of partition table
  181. mov di,Tablel ; es:di -> local start/size table
  182. nextent:
  183. cmp byte ptr [si+4],0
  184. jnz @f
  185. add si,16
  186. loop nextent
  187. jmp short chkfull
  188. @@: add si,8 ; ds:si -> relative sector field
  189. movsw ; start low
  190. movsw ; start high
  191. movsw ; count low
  192. movsw ; count high
  193. inc al ; remember number of used entries
  194. loop nextent
  195. ;
  196. ; See if the partition table is full.
  197. ;
  198. chkfull:
  199. cmp al,4
  200. jne @f
  201. mov ax,0ffffh
  202. je done1
  203. ;
  204. ; Sort the local start/size table. Before calling crt
  205. ; make sure ds addresses DGROUP.
  206. ;
  207. @@: push ds
  208. push DGROUP
  209. pop ds
  210. push ax ; save table length
  211. push SEG CompareStartSize
  212. push OFFSET CompareStartSize ; compare routine pointer
  213. push SIZE START_AND_SIZE ; size of each element
  214. push ax ; number of elements to sort
  215. push Table ; array of elements to sort
  216. call _qsort
  217. add sp,12
  218. pop bx ; restore table length
  219. pop ds
  220. ;
  221. ; Put a "fence" entry at the end of the table
  222. ; for space at the end of the disk.
  223. ;
  224. mov al,SIZE START_AND_SIZE
  225. mul bl ; ax = byte offset to fence entry
  226. inc bl ; account for fence entry
  227. les di,Table
  228. add di,ax ; es:di -> fence entry
  229. mov ax,DiskSizel
  230. mov es:[di].PartStartl,ax
  231. mov ax,DiskSizeh
  232. mov es:[di].PartStarth,ax
  233. mov es:[di].PartSizel,1
  234. mov es:[di].PartSizeh,0
  235. ;
  236. ; Initialize for loop. The first space starts on the first sector
  237. ; of the second head.
  238. ;
  239. mov al,SectorsPerTrack
  240. cbw
  241. mov FreeStartl,ax
  242. mov FreeStarth,0
  243. mov cl,bl
  244. xor ch,ch ; cx = # entries in table
  245. les di,Table ; es:di -> start/offset table
  246. jmp short aligned1
  247. ;
  248. ; Get the start of the partition and align to cylinder boundary
  249. ;
  250. nextspace:
  251. mov dx,FreeStarth
  252. mov ax,FreeStartl ; dx:ax = start of free space
  253. div SectorsPerCylinder ; dx = sector within cylinder
  254. cmp dx,0 ; already aligned?
  255. jz aligned1 ; yes
  256. mov bx,SectorsPerCylinder
  257. sub bx,dx ; bx = adjustment to next boundary
  258. add FreeStartl,bx
  259. adc FreeStarth,0 ; FreeStart now aligned
  260. aligned1:
  261. mov dx,es:[di].PartStarth
  262. mov ax,es:[di].PartStartl ; dx:ax = start of partition
  263. sub ax,FreeStartl
  264. sbb dx,FreeStarth ; dx:ax = size of free space
  265. push ax
  266. push dx
  267. ;
  268. ; Now make sure the end of the free space is aligned.
  269. ;
  270. add ax,FreeStartl
  271. adc dx,FreeStarth ; dx:ax = first sector past free space
  272. div SectorsPerCylinder ; dx = sector within cylinder (may be 0)
  273. mov bx,dx
  274. pop dx
  275. pop ax ; dx:ax = size of free space
  276. sub ax,bx
  277. sbb dx,0 ; dx:ax = size of aligned free space
  278. js nextspace1 ; just in case
  279. ;
  280. ; Check the free space to see if it's large enough.
  281. ;
  282. cmp dx,MinimumSectorCounth
  283. ja makepart ; it's large enough
  284. jb nextspace1
  285. cmp ax,MinimumSectorCountl
  286. jae makepart
  287. nextspace1:
  288. mov ax,es:[di].PartStartl
  289. add ax,es:[di].PartSizel
  290. mov FreeStartl,ax
  291. mov ax,es:[di].PartStarth
  292. adc ax,es:[di].PartSizeh
  293. mov FreeStarth,ax ; next space is after this partition
  294. add di,SIZE START_AND_SIZE ; point at next table entry
  295. loop nextspace
  296. mov ax,cx ; no room, set ax for error return
  297. dec ax
  298. jmp done1
  299. ;
  300. ; If we get here, we've found a free space that will work
  301. ; for our partition.
  302. ;
  303. ; FreeStart has the start of the free space.
  304. ;
  305. makepart:
  306. mov ax,FreeStartl
  307. add ax,MinimumSectorCountl
  308. mov dx,FreeStarth
  309. adc dx,MinimumSectorCounth
  310. div SectorsPerCylinder ; dx = sector within cylinder
  311. cmp dx,0 ; aligned already?
  312. jz @f ; yes
  313. mov bx,SectorsPerCylinder
  314. sub bx,dx ; bx = adjustment to next cyl boundary
  315. add MinimumSectorCountl,bx
  316. adc MinimumSectorCounth,0
  317. ;
  318. ; Now MinimumSectorCount has the actual sector count.
  319. ; Find a free table entry. We know there is one or else
  320. ; we'd have errored out a while ago.
  321. ;
  322. @@: lds si,SectorBuffer
  323. add si,1beh ; ds:si -> partition table
  324. @@: cmp byte ptr [si+4],0
  325. jz makepart1
  326. add si,16
  327. jmp short @b
  328. makepart1:
  329. mov ax,FreeStartl
  330. mov dx,FreeStarth
  331. mov [si+8],ax
  332. mov [si+10],dx
  333. add si,1
  334. call pMakeCHS
  335. mov ax,MinimumSectorCountl
  336. mov dx,MinimumSectorCounth
  337. mov [si+11],ax
  338. mov [si+13],dx
  339. add ax,FreeStartl
  340. adc dx,FreeStarth
  341. sub ax,1
  342. sbb dx,0
  343. add si,4
  344. call pMakeCHS ; al = xint13 required flag
  345. sub si,1 ; ds:si -> system id byte
  346. ;
  347. ; Figure out the partition id.
  348. ; al is xint13 required flag
  349. ;
  350. mov dx,PartitionClass
  351. mov ah,SystemId
  352. call pDetermineSystemId
  353. mov [si],al ; store away system id
  354. sub si,4 ; ds:si -> partition table entry
  355. call pNewPartitionRecord
  356. cmp ax,0ffffh
  357. je done1 ; error, bail now
  358. ;
  359. ; Phew. Write out the master boot sector.
  360. ;
  361. push ax ; save partition id
  362. push SectorBuffer
  363. push 1
  364. push 0
  365. push 0
  366. push DiskHandle
  367. call _WriteDisk
  368. add sp,14 ; ax set for return
  369. pop dx ; dx = partition id
  370. cmp ax,0 ; error?
  371. jne @f ; no
  372. dec ax ; ax = -1 for error return
  373. jmp short done1
  374. @@: mov ax,dx ; ax = partition id for return
  375. done1:
  376. push ax
  377. push Table
  378. push DGROUP
  379. pop ds ; address DGROUP for crt
  380. call _free
  381. add sp,4
  382. pop ax
  383. done2:
  384. pop di
  385. pop si
  386. pop bx
  387. pop es
  388. pop ds
  389. leave
  390. retf
  391. _MakePartitionAtStartOfDisk endp
  392. Comparand1 equ dword ptr [bp+6]
  393. Comparand2 equ dword ptr [bp+10]
  394. CompareStartSize proc far
  395. push bp
  396. mov bp,sp
  397. push ds
  398. push es
  399. push di
  400. push si
  401. lds si,Comparand1
  402. les di,Comparand2
  403. mov dx,es:[di].PartStarth
  404. mov ax,es:[di].PartStartl
  405. cmp [si].PartStarth,dx
  406. jb less1
  407. ja greater1
  408. cmp [si].PartStartl,ax
  409. jb less1
  410. ja greater1
  411. xor ax,ax
  412. jmp short compdone
  413. less1:
  414. mov ax,0ffffh
  415. jmp short compdone
  416. greater1:
  417. mov ax,1
  418. compdone:
  419. pop si
  420. pop di
  421. pop es
  422. pop ds
  423. leave
  424. retf
  425. CompareStartSize endp
  426. ;++
  427. ;
  428. ; INT
  429. ; _far
  430. ; MakePartitionAtEndOfEmptyDisk(
  431. ; IN HDISK DiskHandle,
  432. ; OUT FPVOID SectorBuffer,
  433. ; IN ULONG MinimumSectorCount,
  434. ; IN BOOL NewMasterBootCode
  435. ; );
  436. ;
  437. ; Routine Description:
  438. ;
  439. ; This routine creates an partition at the very end of a disk.
  440. ; The disk MUST be completely empty. If no valid MBR exists,
  441. ; one will be created.
  442. ;
  443. ; The partition will be made active.
  444. ;
  445. ; Arguments:
  446. ;
  447. ; DiskHandle - supplies handle to open disk, from OpenDisk().
  448. ;
  449. ; SectorBuffer - supplies a pointer to a buffer suitable for use
  450. ; for i/o of a single sector. This buffer must not
  451. ; cross a DMA boundary, but the caller is responsible
  452. ; for ensuring this.
  453. ;
  454. ; MinimumSectorCount - supplies minimum number of sectors
  455. ; for the partition. The actual size may be larger
  456. ; to account for rounding, etc.
  457. ;
  458. ; This routine does NOT properly deal with partitions
  459. ; that start on cylinder 0 or are larger than the size
  460. ; of the disk! The caller must ensure that these cases
  461. ; do not occur.
  462. ;
  463. ; NewMasterBootCode - if non-0, then new master boot code will
  464. ; be written regardless of the current state of the MBR.
  465. ;
  466. ; Return Value:
  467. ;
  468. ; Partition id of newly created partition.
  469. ; -1 means failure
  470. ;
  471. ;--
  472. DiskHandle equ dword ptr [bp+6]
  473. DiskHandlel equ word ptr [bp+6]
  474. DiskHandleh equ word ptr [bp+8]
  475. SectorBuffer equ dword ptr [bp+10]
  476. SectorBufferl equ word ptr [bp+10]
  477. SectorBufferh equ word ptr [bp+12]
  478. MinimumSectorCount equ dword ptr [bp+14]
  479. MinimumSectorCountl equ word ptr [bp+14]
  480. MinimumSectorCounth equ word ptr [bp+16]
  481. NewMasterBootCode equ word ptr [bp+18]
  482. ExtSecCnth equ word ptr [bp-2]
  483. ExtSecCntl equ word ptr [bp-4]
  484. ExtSecCnt equ dword ptr [bp-4]
  485. Cylinders equ word ptr [bp-6]
  486. Heads equ word ptr [bp-8]
  487. SectorsPerTrack equ byte ptr [bp-9]
  488. Int13UnitNumber equ byte ptr [bp-10]
  489. SectorsPerCylinder equ word ptr [bp-12]
  490. DiskSizeh equ word ptr [bp-14]
  491. DiskSizel equ word ptr [bp-16]
  492. DiskSize equ dword ptr [bp-16]
  493. DiskId equ word ptr [bp-18]
  494. public _MakePartitionAtEndOfEmptyDisk
  495. _MakePartitionAtEndOfEmptyDisk proc far
  496. push bp
  497. mov bp,sp
  498. sub sp,18
  499. push ds
  500. push es
  501. push bx
  502. push si
  503. push di
  504. ;
  505. ; Get disk info. This also makes sure the handle is open,
  506. ; calculates the number of sectors we can address on the disk,
  507. ; and the number of sectors in a cylinder.
  508. ;
  509. call near ptr pGetDiskValues
  510. jnc @f
  511. mov ax,0ffffh
  512. jc mpaod_4
  513. @@:
  514. ;
  515. ; Read the mbr.
  516. ;
  517. push SectorBuffer
  518. push 1
  519. push 0
  520. push 0
  521. push DiskHandle
  522. call _ReadDisk
  523. add sp,14
  524. cmp ax,0
  525. jne @f
  526. dec ax ; ax = -1 for error return
  527. jmp mpaod_4
  528. ;
  529. ; Check the mbr. If not valid, make it valid.
  530. ;
  531. @@: les di,SectorBuffer
  532. cmp NewMasterBootCode,0
  533. jnz makembr ; caller wants new master boot code
  534. cmp byte ptr es:[di+510],055h
  535. jne makembr
  536. cmp byte ptr es:[di+511],0aah
  537. je mbrok
  538. makembr:
  539. mov byte ptr es:[di+510],055h
  540. mov byte ptr es:[di+511],0aah
  541. mov si,offset DGROUP:_x86BootCode
  542. mov cx,1b8h/2 ; don't overwrite NTFT sig or table
  543. rep movsw
  544. mbrok:
  545. ;
  546. ; Make sure all entries are empty.
  547. ;
  548. lds si,SectorBuffer
  549. add si,1beh
  550. mov cx,0
  551. mov ax,cx
  552. dec ax ; ax = -1
  553. cmp [si+04h],cl
  554. jnz mpaod_4
  555. cmp [si+14h],cl
  556. jnz mpaod_4
  557. cmp [si+24h],cl
  558. jnz mpaod_4
  559. cmp [si+34h],cl
  560. jnz mpaod_4
  561. ;
  562. ; Calculate the starting sector. We don't worry about aligning
  563. ; the end sector because in the conventional int13 case we
  564. ; calculated the disk size based on cylinder count, which means
  565. ; it is guaranteed to be aligned; in the xint13 case CHS isn't
  566. ; even relevent and in any case there won't be any partitions
  567. ; on the disk after this one.
  568. ;
  569. mov ax,DiskSizel
  570. sub ax,MinimumSectorCountl
  571. mov dx,DiskSizeh
  572. sbb dx,MinimumSectorCounth ; dx:ax = start sector of partition
  573. mov [si+8],ax
  574. mov [si+10],dx ; save in partition table
  575. div SectorsPerCylinder ; ax = cyl, dx = sector within cyl
  576. sub [si+8],dx ; note: dx is zero if already aligned
  577. sbb [si+10],cx ; partition table has aligned start
  578. mov ax,MinimumSectorCountl
  579. add ax,dx ; grow to account for alignment
  580. mov [si+12],ax
  581. mov ax,MinimumSectorCounth
  582. adc ax,cx
  583. mov [si+14],ax ; put adjusted size in partition table
  584. ;
  585. ; Make the partition active.
  586. ;
  587. mov byte ptr [si],80h
  588. ;
  589. ; Fill in CHS values for the partition
  590. ;
  591. mov ax,[si+8]
  592. mov dx,[si+10] ; dx:ax = start sector
  593. inc si ; ds:si -> start CHS in part table
  594. call pMakeCHS
  595. mov ax,[si+7]
  596. add ax,[si+11]
  597. mov dx,[si+9]
  598. adc dx,[si+13]
  599. sub ax,1
  600. sbb dx,0 ; dx:ax = last sector
  601. add si,4 ; ds:si -> end CHS in part table
  602. call pMakeCHS ; al = overflow flag
  603. ;
  604. ; Figure out the system id.
  605. ; al is xint13 required flag
  606. ;
  607. mov dx,PARTCLASS_FAT
  608. call pDetermineSystemId
  609. mov [si-1],al ; store away system id
  610. ;
  611. ; Build a partition record for this guy and add to list.
  612. ;
  613. sub si,5 ; ds:si -> partition table entry
  614. call pNewPartitionRecord
  615. cmp ax,0ffffh
  616. je mpaod_4 ; error, ax set for return
  617. ;
  618. ; The mbr is ready, write it out.
  619. ;
  620. push ax
  621. push SectorBuffer
  622. push 1
  623. push 0
  624. push 0
  625. push DiskHandle
  626. call _WriteDisk
  627. add sp,14
  628. mov dx,ax
  629. pop ax ; ax = partition id
  630. cmp dx,0 ; write error?
  631. jnz mpaod_4 ; no, ax = partition id for exit
  632. mov ax,0ffffh ; set ax for error return
  633. mpaod_4:
  634. pop di
  635. pop si
  636. pop bx
  637. pop es
  638. pop ds
  639. leave
  640. retf
  641. _MakePartitionAtEndOfEmptyDisk endp
  642. ;++
  643. ;
  644. ; INT
  645. ; _far
  646. ; ReinitializePartitionTable(
  647. ; IN HDISK DiskHandle,
  648. ; OUT FPVOID SectorBuffer
  649. ; );
  650. ;
  651. ; Routine Description:
  652. ;
  653. ; This routine wipes a disk completely clean by clearning
  654. ; the partition table and writing new boot code.
  655. ;
  656. ; NOTE: after this routine, partition ids may change!
  657. ;
  658. ; Arguments:
  659. ;
  660. ; DiskHandle - supplies handle to open disk, from OpenDisk().
  661. ;
  662. ; SectorBuffer - supplies a pointer to a buffer suitable for use
  663. ; for i/o of a single sector. This buffer must not
  664. ; cross a DMA boundary, but the caller is responsible
  665. ; for ensuring this.
  666. ;
  667. ; Return Value:
  668. ;
  669. ; The new number of total partitions, -1 if error
  670. ;
  671. ;--
  672. DiskHandle equ dword ptr [bp+6]
  673. SectorBuffer equ dword ptr [bp+10]
  674. public _ReinitializePartitionTable
  675. _ReinitializePartitionTable proc far
  676. push bp
  677. mov bp,sp
  678. push ds
  679. push es
  680. push si
  681. push di
  682. pushf
  683. ;
  684. ; This is very simple. Move template boot code
  685. ; into the sector buffer and write it out.
  686. ;
  687. les di,SectorBuffer
  688. push DGROUP
  689. pop ds
  690. mov si,OFFSET DGROUP:_x86BootCode
  691. mov cx,512/2
  692. cld
  693. rep movsw
  694. push SectorBuffer
  695. push 1
  696. push 0
  697. push 0
  698. push DiskHandle
  699. call _WriteDisk
  700. add sp,14
  701. cmp ax,0
  702. jnz rpt2
  703. dec ax ; ax = -1 for return
  704. jmp short rpt8
  705. ;
  706. ; Now go through the partition list, removing all entries that were
  707. ; on this disk.
  708. ;
  709. rpt2:
  710. les di,DiskHandle
  711. mov bx,es:[di].DiskInfoDiskId ; bx = id of disk we're wiping
  712. mov dx,[PartitionListCount]
  713. mov si,OFFSET DGROUP:PartitionList ; ds:si = &PartitionList
  714. .errnz PartInfoNext
  715. rpt3:
  716. mov cx,[si].PartInfoNextl
  717. or cx,[si].PartInfoNexth
  718. jz rpt5 ; done
  719. les di,[si].PartInfoNext ; es:di -> current, ds:si -> prev
  720. cmp es:[di].PartInfoDiskId,bx ; partition on disk we wiped?
  721. jne rpt4 ; no
  722. dec dx ; one fewer total partitions
  723. mov ax,es:[di].PartInfoNextl
  724. mov [si].PartInfoNextl,ax
  725. mov ax,es:[di].PartInfoNexth
  726. mov [si].PartInfoNexth,ax ; prev->next = current->next
  727. push bx
  728. push ds
  729. push DGROUP
  730. pop ds ; make sure we're addressing DGROUP
  731. push es
  732. push di
  733. call _free ; free(current)
  734. add sp,4
  735. pop ds
  736. pop bx ; restore disk id
  737. jmp short rpt3
  738. rpt4: mov ax,es
  739. mov ds,ax
  740. mov si,di ; prev = current
  741. jmp short rpt3
  742. rpt5:
  743. push DGROUP
  744. pop ds
  745. mov [PartitionListCount],dx ; save new count
  746. mov ax,dx ; ax = return value
  747. ;
  748. ; Now reassign partition ids so they are contiguous.
  749. ;
  750. mov si,OFFSET DGROUP:PartitionList
  751. rpt6: mov cx,[si].PartInfoNextl
  752. or cx,[si].PartInfoNexth
  753. jz rpt8
  754. dec dx
  755. lds si,[si].PartInfoNext
  756. mov [si].PartInfoDiskId,dx
  757. jmp short rpt6
  758. rpt8:
  759. popf
  760. pop di
  761. pop si
  762. pop es
  763. pop ds
  764. leave
  765. retf
  766. _ReinitializePartitionTable endp
  767. ;
  768. ; dx:ax = sector to translate
  769. ; ds:si -> CHS bytes
  770. ;
  771. pMakeCHS proc near
  772. div SectorsPerCylinder ; ax = cylinder, dx = sector in cyl
  773. cmp ax,Cylinders ; overflow?
  774. jb chsok ; no, continue
  775. push 1 ; overflow flag
  776. mov ax,Cylinders
  777. dec ax ; store max cylinder in table
  778. jmp short chs1
  779. chsok:
  780. push 0 ; no overflow flag
  781. chs1: mov cx,ax
  782. xchg cl,ch
  783. shl cl,6
  784. ;
  785. ; small divide is acceptable here since head is 1-255, sector is
  786. ; 1-63 (and thus max sector within cyl is (63*256)-1).
  787. ;
  788. mov ax,dx
  789. div SectorsPerTrack ; al = head, ah = sector
  790. inc ah ; sector is 1-based
  791. or cl,ah ; cx has cyl/sector in int13 format
  792. storechs:
  793. mov [si+1],cx ; store in partition table entry
  794. mov [si],al ; store head in partition table entry
  795. pop ax ; return overflow flag
  796. ret
  797. pMakeCHS endp
  798. ;
  799. ; ds:si -> partition table entry with lba and sysid fields filled in
  800. ; preserves none
  801. ; returns new part ordinal or -1
  802. ;
  803. pNewPartitionRecord proc near
  804. ;
  805. ; Allocate a new partition record
  806. ;
  807. push ds
  808. push si
  809. push DGROUP
  810. pop ds
  811. mov si,OFFSET DGROUP:PartitionListCount
  812. push [si] ; save count for later
  813. inc word ptr [si]
  814. push SIZE PART_INFO
  815. call _malloc
  816. add sp,2
  817. pop bx ; restore partition count
  818. pop si
  819. pop ds ; ds:si -> partition table entry
  820. mov cx,ax
  821. or cx,dx
  822. jnz @f ; malloc ok
  823. mov ax,0ffffh
  824. jz npr_done ; return failure
  825. @@: push bx
  826. mov cx,DGROUP
  827. mov es,cx
  828. mov di,OFFSET DGROUP:PartitionList ; es:di = &PartitionList
  829. .errnz PartInfoNext
  830. mov cx,es:[di] ; get current head of list in bx:cx
  831. mov bx,es:[di+2]
  832. mov es:[di],ax
  833. mov es:[di+2],dx ; insert new record at head of list
  834. mov es,dx
  835. mov di,ax ; es:di -> new record
  836. mov es:[di].PartInfoNextl,cx
  837. mov es:[di].PartInfoNexth,bx
  838. mov ax,DiskId
  839. mov es:[di].PartInfoDiskId,ax
  840. pop ax ; partition ordinal, also return val
  841. mov es:[di].PartInfoOrdinal,ax
  842. mov cx,[si+8]
  843. mov es:[di].PartInfoStartSectorl,cx
  844. mov cx,[si+10]
  845. mov es:[di].PartInfoStartSectorh,cx
  846. mov cx,[si+12]
  847. mov es:[di].PartInfoSectorCountl,cx
  848. mov cx,[si+14]
  849. mov es:[di].PartInfoSectorCounth,cx
  850. mov cl,[si+4]
  851. mov es:[di].PartInfoSystemId,cl
  852. ;
  853. ; Indicate partition not open
  854. ;
  855. mov es:[di].PartInfoPartOpen,0
  856. mov es:[di].PartInfoDiskHandlel,0
  857. mov es:[di].PartInfoDiskHandleh,0
  858. npr_done:
  859. ret
  860. pNewPartitionRecord endp
  861. ;
  862. ; No params, nested in top-level routines above
  863. ;
  864. pGetDiskValues proc near
  865. ;
  866. ; Get disk info. This also makes sure the handle is open.
  867. ;
  868. push ss
  869. lea bx,DiskId
  870. push bx
  871. push ss
  872. lea bx,ExtSecCnt
  873. push bx
  874. push ss
  875. lea bx,Cylinders
  876. push bx
  877. push ss
  878. lea bx,Heads
  879. push bx
  880. push ss
  881. lea bx,SectorsPerTrack
  882. push bx
  883. push ss
  884. lea bx,Int13UnitNumber
  885. push bx
  886. push DiskHandle
  887. call _GetDiskInfoByHandle
  888. add sp,28
  889. cmp ax,0
  890. jnz @f
  891. stc
  892. ret
  893. ;
  894. ; Calculate the number of sectors we can address on the disk.
  895. ; Also precalculate the number of sectors in a cylinder.
  896. ;
  897. @@: mov al,SectorsPerTrack
  898. cbw
  899. mul Heads ; ax = sectors per cylinder, dx = 0
  900. mov SectorsPerCylinder,ax
  901. cmp ExtSecCntl,dx
  902. jnz usexcnt
  903. cmp ExtSecCnth,dx
  904. jnz usexcnt
  905. mul Cylinders ; dx:ax = sectors on disk
  906. jmp short storsize
  907. usexcnt:
  908. mov dx,ExtSecCnth
  909. mov ax,ExtSecCntl
  910. storsize:
  911. mov DiskSizeh,dx
  912. mov DiskSizel,ax
  913. clc
  914. gv3: ret
  915. pGetDiskValues endp
  916. ;
  917. ; No params, nested in top-level routines above
  918. ; al = xint13 required flag
  919. ; dx = partition class
  920. ; ah = sysid if unknown class
  921. ;
  922. ; returns system id in al
  923. ;
  924. pDetermineSystemId proc near
  925. cmp dx,PARTCLASS_FAT
  926. jne tryfat32
  927. cmp al,0
  928. je @f
  929. mov al,0eh ; type e = fat xint13
  930. jmp short gotsysid
  931. @@: cmp MinimumSectorCounth,0
  932. jne bigfat
  933. cmp MinimumSectorCountl,32680
  934. jb fat12
  935. mov al,4 ; type 4 = fat16
  936. jmp short gotsysid
  937. fat12: mov al,1 ; type 1 = fat12
  938. jmp short gotsysid
  939. bigfat: mov al,6 ; type 6 = huge fat
  940. jmp short gotsysid
  941. tryfat32:
  942. cmp dx,PARTCLASS_FAT32
  943. jne tryntfs
  944. cmp al,0
  945. jne @f
  946. mov al,0bh ; type b = fat32 non-xint13
  947. jmp short gotsysid
  948. @@: mov al,0ch ; type c = fat32 xint13
  949. jmp short gotsysid
  950. tryntfs:
  951. cmp dx,PARTCLASS_NTFS
  952. jne othersys
  953. mov al,7 ; type 7 = ntfs
  954. jmp short gotsysid
  955. othersys:
  956. mov al,ah
  957. gotsysid:
  958. ret
  959. pDetermineSystemId endp
  960. end