source: trunk/bootcode/special/lvm.asm@ 76

Last change on this file since 76 was 76, checked in by Ben Rietbroek, 8 years ago

Removed the ancient 'ReleaseCode' conditional [v1.1.1-testing]

This was used in pre v1.07 versions to create a DOS .COM executable
for debugging. It has never been used in v1.07+ versions and debugging
is now done using the serial port from native AirBoot. Time to get rid
of this unused stuff.

CAUTION:
This is a testbuild !
AirBoot uses the BIOS to access disks and a small coding error can trash
partition tables or other vital disk structures. You are advised to make
backups of TRACK0 and EBRs before using this testbuild. More info at:
https://rousseaux.github.io/netlabs.air-boot/pdf/AirBoot-v1.1.0-manual.pdf

File size: 20.4 KB
Line 
1; AiR-BOOT (c) Copyright 1998-2008 M. Kiewitz
2;
3; This file is part of AiR-BOOT
4;
5; AiR-BOOT is free software: you can redistribute it and/or modify it under
6; the terms of the GNU General Public License as published by the Free
7; Software Foundation, either version 3 of the License, or (at your option)
8; any later version.
9;
10; AiR-BOOT is distributed in the hope that it will be useful, but WITHOUT ANY
11; WARRANTY: without even the implied warranty of MERCHANTABILITY or FITNESS
12; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13; details.
14;
15; You should have received a copy of the GNU General Public License along with
16; AiR-BOOT. If not, see <http://www.gnu.org/licenses/>.
17;
18;---------------------------------------------------------------------------
19; AiR-BOOT / LVM
20;---------------------------------------------------------------------------
21
22IFDEF MODULE_NAMES
23DB 'LVM',0
24ENDIF
25
26LVM_InitCRCTable Proc Near
27 ; Initializes our LVM-CRC-Table
28 xor cl, cl
29 mov di, offset [LVM_CRCTable]
30 LVM_ICRCT_Loop:
31 ;movzx ax, cl
32 mov al,cl
33 mov ah,0
34 xor dx, dx ; DX:AX - CRC-Value
35 mov ch, 8
36 LVM_ICRCT_Loop2:
37 shr dx, 1
38 rcr ax, 1 ; Shift value 1 to the right
39 jnc LVM_ICRCT_NoXOR
40 xor dx, 0EDB8h
41 xor ax, 8320h
42 LVM_ICRCT_NoXOR:
43 dec ch
44 jnz LVM_ICRCT_Loop2
45 mov wptr [di+0], ax
46 mov wptr [di+2], dx
47 add di, 4
48 add cl, 1
49 jnc LVM_ICRCT_Loop
50 ret
51LVM_InitCRCTable EndP
52
53; Calculates an LVM-Sector CRC of a given sector
54; In: DS:SI - Points to Sector...
55; Out: DX:AX - LVM CRC
56; Destroyed: None
57LVM_GetSectorCRC Proc Near Uses bx cx
58 push word ptr [si+LocLVM_CRC+00]
59 push word ptr [si+LocLVM_CRC+02]
60 push si
61 mov word ptr [si+LocLVM_CRC], 0
62 mov word ptr [si+LocLVM_CRC+2], 0
63 mov ax, -1
64 mov dx, -1
65 mov cx, 512
66 LVM_GSCRC_Loop:
67 xor bh, bh
68 mov bl, al ; Save last byte to BL
69 mov al, ah
70 mov ah, dl
71 mov dl, dh
72 xor dh, dh ; SHR DX:AX, 8
73 xor bl, [si]
74 inc si ; XOR last byte with [data]
75 shl bx, 1
76 shl bx, 1
77 xor ax, word ptr [LVM_CRCTable+bx+0]
78 xor dx, word ptr [LVM_CRCTable+bx+2] ; XOR with CRC-Table
79 loop LVM_GSCRC_Loop
80 pop si
81 pop word ptr [si+LocLVM_CRC+2]
82 pop word ptr [si+LocLVM_CRC]
83 ret
84LVM_GetSectorCRC EndP
85
86; Checks ds:[SI], if a valid LVM Signature is found (sets carry in that case)
87; This does not check for valid LVM CRC (which also needs to be done)
88; In: DS:SI - Sector that needs to get checked...
89; Out: Carry set, if valid LVM signature found
90; Destroyed: None
91LVM_CheckSectorSignature Proc Near
92 test byte ptr [CFG_IgnoreLVM], 1 ; We are supposed to ignore LVM, so
93 jnz LVMCSS_InvalidSignature ; any sector is bad!
94 cmp word ptr [si+LocLVM_SignatureStart], 5202h
95 jne LVMCSS_InvalidSignature
96 cmp word ptr [si+LocLVM_SignatureStart+2], 'BM'
97 jne LVMCSS_InvalidSignature
98 cmp word ptr [si+LocLVM_SignatureStart+4], 'MP'
99 jne LVMCSS_InvalidSignature
100 cmp word ptr [si+LocLVM_SignatureStart+6], 'DF'
101 jne LVMCSS_InvalidSignature
102 stc
103 ret
104 LVMCSS_InvalidSignature:
105 clc
106 ret
107LVM_CheckSectorSignature EndP
108
109; Checks Sector for a valid LVM CRC is encountered
110; First one should check for a valid signature and call this later.
111; In: DS:SI - Sector that needs to get checked...
112; Out: Carry set, if LVM CRC valid
113; Destroyed: None
114LVM_CheckSectorCRC Proc Near Uses ax dx
115 call LVM_GetSectorCRC
116 cmp ax, word ptr [si+LocLVM_CRC]
117 jne LVMCSCRC_BadCRC
118 cmp dx, word ptr [si+LocLVM_CRC+2]
119 jne LVMCSCRC_BadCRC
120 stc
121 ret
122 LVMCSCRC_BadCRC:
123 clc
124 ret
125LVM_CheckSectorCRC EndP
126
127; Updates Sector with valid LVM CRC
128; This one doesn't check, if it's really an LVM sector, so check before!
129; In: DS:SI - Sector that needs to get checked...
130; Out: None, CRC updated
131; Destroyed: None
132LVM_UpdateSectorCRC Proc Near Uses ax dx
133 call LVM_GetSectorCRC
134 mov word ptr [si+LocLVM_CRC], ax
135 mov word ptr [si+LocLVM_CRC+2], dx
136 ret
137LVM_UpdateSectorCRC EndP
138
139; Searches for a partition in LVM Information Sector and sets SI to point to
140; the LVM-entry. It will also set CARRY then.
141; In: DX:AX - LBA starting sector of partition to be searched
142; DS:SI - Valid (previously checked) LVM-Information-Sector
143; Out: Carry set, if partition found
144; DS:SI - points to LVM information entry
145; Destroyed: None
146LVM_SearchForPartition Proc Near Uses cx
147 cmp byte ptr [si+LocLVM_SignatureStart], LocLVM_SignatureByte0
148 jne LVMSFP_NotFound ; Quick Check, if LVM sector there
149 add si, LocLVM_StartOfEntries
150 mov cl, LocLVM_MaxEntries
151 LVMSFP_Loop:
152 cmp ax, [si+LocLVM_PartitionStart]
153 jne LVMSFP_NextEntry
154 cmp dx, [si+LocLVM_PartitionStart+2]
155 je LVMSFP_FoundIt
156 LVMSFP_NextEntry:
157 add si, LocLVM_LenOfEntry
158 dec cl
159 jnz LVMSFP_Loop
160 LVMSFP_NotFound:
161 clc
162 ret
163 LVMSFP_FoundIt:
164 stc
165 ret
166LVM_SearchForPartition EndP
167
168
169; Gets a drive-letter from the LVM-info of a partition. (if it exists)
170; In: BX:CX - LBA starting sector of partition to be searched
171; DL = Physical Disk in BIOS notation. (80h+)
172; Out: CY=1 if LVM-info found, 0 if no LVM-info.
173; AL - drive-letter from LVM-info or zero if no drive-letter
174; assigned or no LVM-info.
175LVM_GetDriveLetter Proc Near Uses bx cx dx si di ds es
176 ; For primary partitions this information is stored in the last
177 ; sector of track0; for all four partition entries in case they
178 ; they are all primary ones.
179 ;
180 ; LVM DLAT info for logical partitions is stored in the sector
181 ; preceding the start of the partition.
182 ;
183 ; Because the LVM info of a logical partition is the easiest to find,
184 ; we do that first. The LVM info for primary partitions is located
185 ; dependent on the geometry in use, so we use a special locater
186 ; call for that. Also, since the LVM info for primaries contains
187 ; info on all 4 entries, we need the partition index to obtain the
188 ; correct drive-letter.
189 ;
190
191 ; See if this is a primary partition
192 ; CY will be set if it is and AL will contain the 0-based
193 ; index in the P-table.
194 ; If it's a logical partition, CY will be clear and AL
195 ; will be set to 0ffh indicating an invalid index.
196 call PART_IsPrimaryPartition
197 mov al,0
198 rcl al,1 ; CY if primary
199 mov dh,al ; Save PRI or LOG
200
201 ; Save PRI/LOG indicator for later use
202 push dx
203
204 ; Load *possible* LVM sector
205 ; This load is only valid if the partition is logical, in which case
206 ; the LVM sector is below the start of the partition.
207 ; If primary, the LVM sector is at a location that
208 ; DriveIO_LoadMasterLVMSector will find out.
209
210 ; Push LBA address
211 push bx
212 push cx
213
214 ; Adjust for logical LVM-sector
215 sub cx,1
216 sbb bx,0
217
218 ; Load the LVM sector
219 push si
220 push di
221 mov si,offset [LVMSector]
222 mov di,ds
223 call DriveIO_LoadSectorLBA ; Change this to normal IO-routine !!!!!!
224 pop di
225 pop si
226
227 ; Restore LBA address
228 pop cx
229 pop bx
230
231 ; Restore PRI/LOG partition indicator in DH
232 pop dx
233
234 ; Test PRI or not
235 test dh,dh
236 ; It's not a PRI so we can use the previously loaded LVM sector
237 jz LVM_GetDriveLetter_is_not_pri
238
239 ;
240 ; It's a PRI so we use the special locator function.
241 ; This locator takes care of extended OS/2 geometry should that be used
242 ;
243 call DriveIO_LoadMasterLVMSector
244
245 LVM_GetDriveLetter_is_not_pri:
246
247
248 ;
249 ; At this stage the LVM-info sector has been loaded at [LVMSector].
250 ; From here we look for an LVM entry for the partition.
251 ; If one is found, based on it's LBA-start, it's driveletter is used
252 ; in case byte 25h in the BPB is zero.
253 ;
254
255
256 ; Search for the partition in the LVM info.
257 ; If found, CY is set and SI points to LVM entry.
258 push si
259 mov ax,cx
260 mov dx,bx
261 mov si,offset [LVMSector]
262 call LVM_SearchForPartition
263 mov bx,si ; BX now points to LVM entry
264 mov dx,0
265 pop si
266
267 mov al,0 ; Setup null driveletter
268 ; Oops, no valid LVM record was used so we have a null driveletter.
269 jnc LVM_GetDriveLetter_null_lvm_dl
270
271 ;
272 ; At this point BX points to the LVM-entry related to the
273 ; partition, whether it was a logical or a primary one.
274 ;
275 mov al,[bx+LocLVM_VolumeLetter]
276 ; Test for zero dtive-letter.
277 test al,al
278 ; Preset CY in case drive-letter is zero.
279 clc
280 jz LVM_GetDriveLetter_null_lvm_dl
281
282 ; We have a non-zero drive-letter, so set CY.
283 stc
284
285 LVM_GetDriveLetter_null_lvm_dl:
286 ret
287LVM_GetDriveLetter EndP
288
289
290
291; Sets a drive-letter in the LVM-info of a partition. (if it exists)
292; In: BX:CX - LBA starting sector of partition to be searched
293; DL = Physical Disk in BIOS notation. (80h+)
294; AL = DriveLetter to set (can be zero to hide partition from LVM)
295; Out: CY=1 if LVM-info found, 0 if no LVM-info.
296LVM_SetDriveLetter Proc Near Uses bx cx dx si di ds es
297 local disk:byte
298 local drive_letter:byte
299 local pri_ind:byte
300 local lvm_log_high:word
301 local lvm_log_low:word
302 ; For primary partitions this information is stored in the last
303 ; sector of track0; for all four partition entries in case they
304 ; they are all primary ones.
305 ;
306 ; LVM DLAT info for logical partitions is stored in the sector
307 ; preceding the start of the partition.
308 ;
309 ; Because the LVM info of a logical partition is the easiest to find,
310 ; we do that first. The LVM info for primary partitions is located
311 ; dependent on the geometry in use, so we use a special locater
312 ; call for that. Also, since the LVM info for primaries contains
313 ; info on all 4 entries, we need the partition index to obtain the
314 ; correct drive-letter.
315 ;
316
317 mov [disk], dl
318
319 ; Store the drive-letter for later use
320 mov [drive_letter], al
321
322
323 ; See if this is a primary partition
324 ; CY will be set if it is and AL will contain the 0-based
325 ; index in the P-table.
326 ; If it's a logical partition, CY will be clear and AL
327 ; will be set to 0ffh indicating an invalid index.
328 call PART_IsPrimaryPartition
329 mov al,0
330 rcl al,1 ; CY if primary
331 mov dh,al ; Save PRI or LOG
332 mov [pri_ind],al
333
334 ; Save PRI/LOG indicator for later use
335 push dx
336
337 ; Load *possible* LVM sector
338 ; This load is only valid if the partition is logical, in which case
339 ; the LVM sector is below the start of the partition.
340 ; If primary, the LVM sector is at a location that
341 ; DriveIO_LoadMasterLVMSector will find out.
342
343 ; Push LBA address
344 push bx
345 push cx
346
347 ; Adjust for logical LVM-sector
348 sub cx,1
349 sbb bx,0
350
351 ; Store LBA address of LVM-sector
352 mov [lvm_log_low],cx
353 mov [lvm_log_high],bx
354
355 ; Load the LVM sector
356 push si
357 push di
358 mov si,offset [LVMSector]
359 mov di,ds
360 call DriveIO_LoadSectorLBA ; Change this to normal IO-routine !!!!!!
361 pop di
362 pop si
363
364 ; Restore LBA address
365 pop cx
366 pop bx
367
368 ; Restore PRI/LOG partition indicator in DH
369 pop dx
370
371 ; Test PRI or not
372 test dh,dh
373 ; It's not a PRI so we can use the previously loaded LVM sector
374 jz LVM_SetDriveLetter_is_not_pri
375
376 ;
377 ; It's a PRI so we use the special locator function.
378 ; This locator takes care of extended OS/2 geometry should that be used
379 ;
380 call DriveIO_LoadMasterLVMSector
381 jnc LVM_SetDriveLetter_null_lvm_dl
382
383 mov ax, word ptr [MasterLVMLBA] ; ARRAY VAN MAKEN !
384 mov [lvm_log_low], ax
385 mov [lvm_log_high], 0
386
387 LVM_SetDriveLetter_is_not_pri:
388
389 ;
390 ; At this stage the LVM-info sector has been loaded at [LVMSector].
391 ; From here we look for an LVM entry for the partition.
392 ; If one is found, based on it's LBA-start, it's driveletter is used
393 ; in case byte 25h in the BPB is zero.
394 ;
395
396 ; Search for the partition in the LVM info.
397 ; If found, CY is set and SI points to LVM entry.
398 push si
399 mov ax,cx
400 mov dx,bx
401 mov si,offset [LVMSector]
402 call LVM_SearchForPartition
403 mov bx,si ; BX now points to LVM entry
404 pop si
405
406 mov al,0 ; Setup null driveletter
407 ; Oops, no valid LVM record was used so we have a null driveletter.
408 jnc LVM_SetDriveLetter_null_lvm_dl
409
410 ;
411 ; At this point BX points to the LVM-entry related to the
412 ; partition, whether it was a logical or a primary one.
413 ;
414 mov al, [drive_letter]
415 mov [bx+LocLVM_VolumeLetter],al
416
417 mov si, offset [LVMSector]
418 call LVM_UpdateSectorCRC
419
420 mov dl, [disk]
421 mov bx, [lvm_log_high]
422 mov ax, [lvm_log_low]
423
424 call DriveIO_SaveSector
425
426 LVM_SetDriveLetter_null_lvm_dl:
427 ret
428LVM_SetDriveLetter EndP
429
430
431
432; Removes a given drive-letter from the whole LVM information sector
433; In: CH - drive-letter (ascii)
434; DS:SI - LVM-Information-Sector
435; Out: LVM-Information-Sector updated (including LVM CRC)
436; Destroyed: None
437LVM_RemoveVolLetterFromSector Proc Near Uses cx
438 cmp bptr [si+LocLVM_SignatureStart], LocLVM_SignatureByte0
439 jne LVMRVLFS_Done ; Quick Check, if LVM sector there
440 push si
441 add si, LocLVM_StartOfEntries
442 mov cl, LocLVM_MaxEntries
443 LVMRVLFS_Loop:
444 cmp ch, [si+LocLVM_VolumeLetter]
445 jne LVMRVLFS_NextEntry
446 ; Reset drive-letter, if matched
447 mov bptr [si+LocLVM_VolumeLetter], 0 ; ASSIGN NEXT FREE HERE... (DOET DUBBEL ALS ZELFDE DL ALS SYS)
448 LVMRVLFS_NextEntry:
449 add si, LocLVM_LenOfEntry
450 dec cl
451 jnz LVMRVLFS_Loop
452 pop si
453 call LVM_UpdateSectorCRC
454 LVMRVLFS_Done:
455 ret
456LVM_RemoveVolLetterFromSector EndP
457
458; Reassigns LVM volume driveletter
459; Will remove the drive-letter from any volume that got it currently
460; and finally change the drive-letter of the given partition
461; In: AL - drive-letter
462; DS:SI - points to partition, that needs that driveletter
463; Out: None
464; Destroyed: AX
465
466LVM_DoLetterReassignment Proc Near Uses bx cx dx si di
467
468 IFDEF AUX_DEBUG
469 pusha
470 mov si, offset dlra
471 call AuxIO_Print
472 call AuxIO_Teletype
473 call AuxIO_TeletypeNL
474 popa
475 ENDIF
476
477 mov di, si ; Save SI in DI (Partition-pointer)
478 mov ch, al ; and AL in CH (drive-letter)
479 xor bx, bx
480 mov cl, CFG_Partitions
481 or cl, cl
482 jz LVMDLR_SkipRemove
483
484 LVMDLR_RemoveLoop:
485 cmp bptr [PartitionVolumeLetters+bx], ch
486 jne LVMDLR_NextPartition
487 ; One volume that has our wanted drive-letter, so remove it!
488 mov dl, bl
489 call PART_GetPartitionPointer ; DL - partition -> SI
490 ; Now set CurPartition_Location for the DriveIO-functions to work
491 mov ax, wptr [si+LocIPT_AbsolutePartTable]
492 mov wptr [CurPartition_Location+0], ax
493 mov ax, wptr [si+LocIPT_AbsolutePartTable+2]
494 mov wptr [CurPartition_Location+2], ax
495 mov ax, wptr [si+LocIPT_LocationPartTable+1]
496 mov wptr [CurPartition_Location+6], ax
497 mov ah, bptr [si+LocIPT_LocationPartTable+0]
498 mov al, [si+LocIPT_Drive]
499 mov wptr [CurPartition_Location+4], ax
500 call DriveIO_LoadLVMSector ; SI points now to LVM-Sector
501 call LVM_RemoveVolLetterFromSector
502
503 call DriveIO_SaveLVMSector ; Save sector
504
505 LVMDLR_NextPartition:
506 inc bx
507 dec cl
508 jnz LVMDLR_RemoveLoop
509
510 LVMDLR_SkipRemove:
511 ; Set CurPartition_Location information of destination partition
512 mov ax, wptr [di+LocIPT_AbsolutePartTable]
513 mov wptr [CurPartition_Location+0], ax
514 mov ax, wptr [di+LocIPT_AbsolutePartTable+2]
515 mov wptr [CurPartition_Location+2], ax
516 mov ah, bptr [di+LocIPT_LocationPartTable+0]
517 mov al, [di+LocIPT_Drive]
518 mov wptr [CurPartition_Location+4], ax
519 mov ax, wptr [di+LocIPT_LocationPartTable+1]
520 mov wptr [CurPartition_Location+6], ax
521 call DriveIO_LoadLVMSector ; SI points now to LVM-Sector
522 mov ax, wptr [di+LocIPT_AbsoluteBegin]
523 mov dx, wptr [di+LocIPT_AbsoluteBegin+2]
524 mov di, si ; Save SI in DI
525 call LVM_SearchForPartition
526 jnc LVMDLR_DestPartNotFound
527 ; Set new volume letter
528 mov bptr [si+LocLVM_VolumeLetter], ch
529 mov si, di ; SI - LVM Sector again
530 call LVM_UpdateSectorCRC ; Update LVM-CRC now
531
532 call DriveIO_SaveLVMSector ; Save sector
533
534 LVMDLR_DestPartNotFound:
535 ; This here is done for safety, because we misuse CurPartition_Location
536 xor ax, ax
537 mov di, offset CurPartition_Location
538 mov cx, 4
539 rep stosw ; NUL out CurPartition_Location
540 ret
541LVM_DoLetterReassignment EndP
542
543
544; This walks the IPT and for each partition it obtains the LVM drive-letter
545; if available. This drive-letter is then marked as in-use in the Map.
546; The FreeDriveletterMap is used by the drive-letter reassignment function
547; to assign a new drive to a data-partition when a system-partition is booted
548; with the same drive-letter. The original drive-letter for the data-partition
549; is saved so it can be restored later when a system is booted that does not
550; use the drive-letter. Note that there can be multiple system-partitions
551; using the same drive-letter and data-partitions can become system-partition
552; by making them bootable. (and vice versa)
553LVM_ComposeFreeDriveletterMap Proc
554
555; get nr of partitions in IPT
556; for each partition get LVM drive-letter and reset bit in map.
557
558LVM_ComposeFreeDriveletterMap EndP
559
Note: See TracBrowser for help on using the repository browser.