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

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

Turned 'LVM_SetDriveLetter' into a dummy function [v1.1.1-testing]

Setting LVM drive-letters is done using the LVM drive-letter
reassignment functions. This 'LVM_SetDriveLetter' function is retained
for possible future implementation as part of the reassignment logic.

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: 17.7 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
59IFDEF AUX_DEBUG
60 IF 0
61 DBG_TEXT_OUT_AUX 'LVM_GetSectorCRC:'
62 PUSHRF
63 ;~ call DEBUG_DumpRegisters
64 ;~ call AuxIO_DumpParagraph
65 ;~ call AuxIO_TeletypeNL
66 POPRF
67 ENDIF
68ENDIF
69
70 push word ptr [si+LocLVM_CRC+00]
71 push word ptr [si+LocLVM_CRC+02]
72 push si
73 mov word ptr [si+LocLVM_CRC], 0
74 mov word ptr [si+LocLVM_CRC+2], 0
75 mov ax, -1
76 mov dx, -1
77 mov cx, 512
78 LVM_GSCRC_Loop:
79 xor bh, bh
80 mov bl, al ; Save last byte to BL
81 mov al, ah
82 mov ah, dl
83 mov dl, dh
84 xor dh, dh ; SHR DX:AX, 8
85 xor bl, [si]
86 inc si ; XOR last byte with [data]
87 shl bx, 1
88 shl bx, 1
89 xor ax, word ptr [LVM_CRCTable+bx+0]
90 xor dx, word ptr [LVM_CRCTable+bx+2] ; XOR with CRC-Table
91 loop LVM_GSCRC_Loop
92 pop si
93 pop word ptr [si+LocLVM_CRC+2]
94 pop word ptr [si+LocLVM_CRC]
95 ret
96LVM_GetSectorCRC EndP
97
98; Checks ds:[SI], if a valid LVM Signature is found (sets carry in that case)
99; This does not check for valid LVM CRC (which also needs to be done)
100; In: DS:SI - Sector that needs to get checked...
101; Out: Carry set, if valid LVM signature found
102; Destroyed: None
103LVM_CheckSectorSignature Proc Near
104 test byte ptr [CFG_IgnoreLVM], 1 ; We are supposed to ignore LVM, so
105 jnz LVMCSS_InvalidSignature ; any sector is bad!
106 cmp word ptr [si+LocLVM_SignatureStart], 5202h
107 jne LVMCSS_InvalidSignature
108 cmp word ptr [si+LocLVM_SignatureStart+2], 'BM'
109 jne LVMCSS_InvalidSignature
110 cmp word ptr [si+LocLVM_SignatureStart+4], 'MP'
111 jne LVMCSS_InvalidSignature
112 cmp word ptr [si+LocLVM_SignatureStart+6], 'DF'
113 jne LVMCSS_InvalidSignature
114 stc
115 ret
116 LVMCSS_InvalidSignature:
117 clc
118 ret
119LVM_CheckSectorSignature EndP
120
121; Checks Sector for a valid LVM CRC is encountered
122; First one should check for a valid signature and call this later.
123; In: DS:SI - Sector that needs to get checked...
124; Out: Carry set, if LVM CRC valid
125; Destroyed: None
126LVM_CheckSectorCRC Proc Near Uses ax bx dx
127 call IsSectorBufferZero ; Zero sector implies bad CRC
128 jz LVMCSCRC_BadCRC
129 call LVM_GetSectorCRC ; Only use after CRC table is valid
130 cmp ax, word ptr [si+LocLVM_CRC]
131 jne LVMCSCRC_BadCRC
132 cmp dx, word ptr [si+LocLVM_CRC+2]
133 jne LVMCSCRC_BadCRC
134 stc ; Indicate CRC is OK
135 ret
136 LVMCSCRC_BadCRC:
137 clc ; Indicate BAD CRC
138 ret
139LVM_CheckSectorCRC EndP
140
141; Checks if a sector is a valid LVM-sector
142; Sector is considered valid LVM-sector if both signature and CRC are correct.
143; IN : DS:SI - Buffer with LVM-sector that needs to be checked...
144; OUT : AL.0 - 1 -> LVM Signature found
145; AL.1 - 1 -> CRC OK
146; CY - Signature and CRC OK, otherwise none or invalid LVM sector
147; Destroyed: None
148LVM_ValidateSector Proc Near
149 xor ax, ax ; Assume no Signature or valid CRC
150 call LVM_CheckSectorSignature ; CF=1 -> Signature OK
151 rcl al, 1 ; Store CF in AL.0
152 call LVM_CheckSectorCRC ; CF=1 -> CRC OK
153 rcl ah, 1 ; Store CF in AH.0
154 shl ah, 1 ; Move it to AH.1
155 or al, ah ; Merge CY results to AL
156 cmp al, 3 ; AH=3 -> Signature and CRC OK
157 clc ; Assume invalid LVM-sector
158 jne @F
159 stc ; AH=3 -> Indicate valid LVM-sector
160 @@:
161 mov ah, 0 ; Don't leave garbage in AH
162 ret
163LVM_ValidateSector EndP
164
165; Updates Sector with valid LVM CRC
166; This one doesn't check, if it's really an LVM sector, so check before!
167; In: DS:SI - Sector that needs to get checked...
168; Out: None, CRC updated
169; Destroyed: None
170LVM_UpdateSectorCRC Proc Near Uses ax dx
171 call LVM_GetSectorCRC
172 mov word ptr [si+LocLVM_CRC], ax
173 mov word ptr [si+LocLVM_CRC+2], dx
174 ret
175LVM_UpdateSectorCRC EndP
176
177; Searches for a partition in LVM Information Sector and sets SI to point to
178; the LVM-entry. It will also set CARRY then.
179; In: DX:AX - LBA starting sector of partition to be searched
180; DS:SI - Valid (previously checked) LVM-Information-Sector
181; Out: Carry set, if partition found
182; DS:SI - points to LVM information entry
183; Destroyed: None
184
185; INVALID LVM RECORD WHEN STICK INSERTED !
186
187LVM_SearchForPartition Proc Near Uses cx
188
189IFDEF AUX_DEBUG
190 IF 0
191 DBG_TEXT_OUT_AUX 'LVM_SearchForPartition:'
192 PUSHRF
193 call DEBUG_DumpRegisters
194 ;~ call AuxIO_DumpParagraph
195 ;~ call AuxIO_TeletypeNL
196 POPRF
197 ENDIF
198ENDIF
199
200 cmp byte ptr [si+LocLVM_SignatureStart], LocLVM_SignatureByte0
201 jne LVMSFP_NotFound ; Quick Check, if LVM sector there
202 add si, LocLVM_StartOfEntries
203 mov cl, LocLVM_MaxEntries
204 LVMSFP_Loop:
205 cmp ax, [si+LocLVM_PartitionStart]
206 jne LVMSFP_NextEntry
207 cmp dx, [si+LocLVM_PartitionStart+2]
208 je LVMSFP_FoundIt
209 LVMSFP_NextEntry:
210 add si, LocLVM_LenOfEntry
211 dec cl
212 jnz LVMSFP_Loop
213 LVMSFP_NotFound:
214 clc
215 ret
216 LVMSFP_FoundIt:
217 stc
218 ret
219LVM_SearchForPartition EndP
220
221
222;------------------------------------------------------------------------------
223; Get the LVM drive-letter for a partition (if available)
224;------------------------------------------------------------------------------
225; IN : SI - Pointer to IPT entry for partition
226; OUT : AL - LVM drive-letter
227; : SI - Pointer to LVM entry in loaded LVM record
228; : CF=1 - No valid LVM sector found, AL not valid
229; NOTE : Besides the drive-letter, AL can be 0 (LVM hidden) or '*' (LVM auto)
230;------------------------------------------------------------------------------
231LVM_GetDriveLetter Proc Near Uses bx cx dx di
232
233IFDEF AUX_DEBUG
234 IF 0
235 DBG_TEXT_OUT_AUX 'LVM_GetDriveLetter:'
236 PUSHRF
237 call DEBUG_DumpRegisters
238 ;~ call AuxIO_DumpParagraph
239 ;~ call AuxIO_TeletypeNL
240 POPRF
241 ENDIF
242ENDIF
243
244 ; Save IPT pointer
245 mov di, si
246
247 ; Get the LBA addresses of the MBR or EBR from the IPT entry
248 mov dl, [si+LocIPT_Drive] ; BIOS disk number
249 mov ax, [si+LocIPT_AbsolutePartTable+00h] ; LBA lo MBR/EBR
250 mov bx, [si+LocIPT_AbsolutePartTable+02h] ; LBA hi MBR/EBR
251
252 ; Try to load the corresponding LVM sector
253 mov si, offset [LVMSector] ; Pointer to buffer
254 call DriveIO_LoadLVMSectorXBR ; Try to load LVM sector
255 jc LVM_GetDriveLetter_no_lvm ; No success
256
257 ; Recall IPT pointer
258 mov si, di
259
260 ; Locate the LVM entry for the partition
261 mov ax, [si+LocIPT_AbsoluteBegin+00h] ; LBA lo of partition
262 mov dx, [si+LocIPT_AbsoluteBegin+02h] ; LBA hi of partition
263 mov si, offset [LVMSector] ; Loaded LVM sector
264 call LVM_SearchForPartition ; Locate entry
265 jnc LVM_GetDriveLetter_no_lvm ; Entry not found
266
267 ; Get the LVM drive-letter
268 mov al, [si+LocLVM_VolumeLetter] ; Can be 0,'*',letter
269
270 ; We're done, indicate success and return
271 clc
272 jmp LVM_GetDriveLetter_done
273
274 LVM_GetDriveLetter_no_lvm:
275 ; Indicate no LVM drive-letter found
276 xor ax, ax
277 mov si, ax
278 stc
279
280 LVM_GetDriveLetter_done:
281
282IFDEF AUX_DEBUG
283 IF 0
284 DBG_TEXT_OUT_AUX 'lgdl_lvmsec'
285 PUSHRF
286 call DEBUG_DumpRegisters
287 mov si, offset [LVMSector]
288 call AuxIO_DumpSector
289 ;~ call AuxIO_DumpParagraph
290 ;~ call AuxIO_TeletypeNL
291 POPRF
292 ENDIF
293ENDIF
294
295 ret
296LVM_GetDriveLetter EndP
297
298
299
300;------------------------------------------------------------------------------
301; Set the LVM drive-letter for a partition (if possible)
302;------------------------------------------------------------------------------
303; IN : SI - Pointer to IPT entry for partition
304; : AL - LVM drive-letter
305; OUT : SI - Pointer to LVM entry in loaded (and saved) LVM record
306; : AL - LVM drive-letter
307; : CF=1 - No valid LVM sector found, AL not valid
308; NOTE : Besides the drive-letter, AL can be 0 (LVM hidden) or '*' (LVM auto)
309;------------------------------------------------------------------------------
310LVM_SetDriveLetter Proc Near Uses bx cx dx di
311
312 ; THIS IS A DUMMY FUNCTION RETURNING FAILURE
313
314 ; Setting LVM drive-letters is handled by the LVM drive-letter
315 ; reassignment functions. This is because when setting LVM
316 ; drive-letters, duplicates and other conditions need to be checked.
317 ; This dummy is only present because it might be implemented in the
318 ; future as part of the drive-letter reassignment logic.
319
320 ; Just indicate failure and return
321 xor ax, ax
322 mov si, ax
323 stc
324 ret
325LVM_SetDriveLetter EndP
326
327
328
329; Removes a given drive-letter from the whole LVM information sector
330; In: CH - drive-letter (ascii)
331; DS:SI - LVM-Information-Sector
332; Out: LVM-Information-Sector updated (including LVM CRC)
333; Destroyed: None
334LVM_RemoveVolLetterFromSector Proc Near Uses cx
335
336IFDEF AUX_DEBUG
337 IF 0
338 DBG_TEXT_OUT_AUX 'LVM_RemoveVolLetterFromSector:'
339 PUSHRF
340 ;~ call DEBUG_DumpRegisters
341 ;~ call AuxIO_DumpParagraph
342 ;~ call AuxIO_TeletypeNL
343 POPRF
344 ENDIF
345ENDIF
346
347 cmp bptr [si+LocLVM_SignatureStart], LocLVM_SignatureByte0
348 jne LVMRVLFS_Done ; Quick Check, if LVM sector there
349 push si
350 add si, LocLVM_StartOfEntries
351 mov cl, LocLVM_MaxEntries
352 LVMRVLFS_Loop:
353 cmp ch, [si+LocLVM_VolumeLetter]
354 jne LVMRVLFS_NextEntry
355 ; Reset drive-letter, if matched
356 mov bptr [si+LocLVM_VolumeLetter], 0 ; ASSIGN NEXT FREE HERE... (DOET DUBBEL ALS ZELFDE DL ALS SYS)
357 LVMRVLFS_NextEntry:
358 add si, LocLVM_LenOfEntry
359 dec cl
360 jnz LVMRVLFS_Loop
361 pop si
362 call LVM_UpdateSectorCRC
363 LVMRVLFS_Done:
364 ret
365LVM_RemoveVolLetterFromSector EndP
366
367; Reassigns LVM volume driveletter
368; Will remove the drive-letter from any volume that got it currently
369; and finally change the drive-letter of the given partition
370; In: AL - drive-letter
371; DS:SI - points to partition, that needs that driveletter
372; Out: None
373; Destroyed: AX
374
375LVM_DoLetterReassignment Proc Near Uses bx cx dx si di
376
377IFDEF AUX_DEBUG
378 IF 0
379 DBG_TEXT_OUT_AUX 'LVM_DoLetterReassignment:'
380 PUSHRF
381 ;~ call DEBUG_DumpRegisters
382 ;~ call AuxIO_DumpParagraph
383 ;~ call AuxIO_TeletypeNL
384 POPRF
385 ENDIF
386ENDIF
387
388 mov di, si ; Save SI in DI (Partition-pointer)
389 mov ch, al ; and AL in CH (drive-letter)
390 xor bx, bx
391 mov cl, CFG_Partitions
392 or cl, cl
393 jz LVMDLR_SkipRemove
394
395 LVMDLR_RemoveLoop:
396 cmp bptr [PartitionVolumeLetters+bx], ch
397 jne LVMDLR_NextPartition
398 ; One volume that has our wanted drive-letter, so remove it!
399 mov dl, bl
400 call PART_GetPartitionPointer ; DL - partition -> SI
401 ; Now set CurPartition_Location for the DriveIO-functions to work
402 mov ax, wptr [si+LocIPT_AbsolutePartTable]
403 mov wptr [CurPartition_Location+0], ax
404 mov ax, wptr [si+LocIPT_AbsolutePartTable+2]
405 mov wptr [CurPartition_Location+2], ax
406 mov ax, wptr [si+LocIPT_LocationPartTable+1]
407 mov wptr [CurPartition_Location+6], ax
408 mov ah, bptr [si+LocIPT_LocationPartTable+0]
409 mov al, [si+LocIPT_Drive]
410 mov wptr [CurPartition_Location+4], ax
411 call DriveIO_LoadLVMSector ; SI points now to LVM-Sector
412 call LVM_RemoveVolLetterFromSector
413
414 call DriveIO_SaveLVMSector ; Save sector
415
416 LVMDLR_NextPartition:
417 inc bx
418 dec cl
419 jnz LVMDLR_RemoveLoop
420
421 LVMDLR_SkipRemove:
422 ; Set CurPartition_Location information of destination partition
423 mov ax, wptr [di+LocIPT_AbsolutePartTable]
424 mov wptr [CurPartition_Location+0], ax
425 mov ax, wptr [di+LocIPT_AbsolutePartTable+2]
426 mov wptr [CurPartition_Location+2], ax
427 mov ah, bptr [di+LocIPT_LocationPartTable+0]
428 mov al, [di+LocIPT_Drive]
429 mov wptr [CurPartition_Location+4], ax
430 mov ax, wptr [di+LocIPT_LocationPartTable+1]
431 mov wptr [CurPartition_Location+6], ax
432 call DriveIO_LoadLVMSector ; SI points now to LVM-Sector
433 mov ax, wptr [di+LocIPT_AbsoluteBegin]
434 mov dx, wptr [di+LocIPT_AbsoluteBegin+2]
435 mov di, si ; Save SI in DI
436 call LVM_SearchForPartition
437 jnc LVMDLR_DestPartNotFound
438 ; Set new volume letter
439 mov bptr [si+LocLVM_VolumeLetter], ch
440 mov si, di ; SI - LVM Sector again
441 call LVM_UpdateSectorCRC ; Update LVM-CRC now
442
443 call DriveIO_SaveLVMSector ; Save sector
444
445 LVMDLR_DestPartNotFound:
446 ; This here is done for safety, because we misuse CurPartition_Location
447 xor ax, ax
448 mov di, offset CurPartition_Location
449 mov cx, 4
450 rep stosw ; NUL out CurPartition_Location
451 ret
452LVM_DoLetterReassignment EndP
453
454
455; This walks the IPT and for each partition it obtains the LVM drive-letter
456; if available. This drive-letter is then marked as in-use in the Map.
457; The FreeDriveletterMap is used by the drive-letter reassignment function
458; to assign a new drive to a data-partition when a system-partition is booted
459; with the same drive-letter. The original drive-letter for the data-partition
460; is saved so it can be restored later when a system is booted that does not
461; use the drive-letter. Note that there can be multiple system-partitions
462; using the same drive-letter and data-partitions can become system-partition
463; by making them bootable. (and vice versa)
464LVM_ComposeFreeDriveletterMap Proc
465
466; get nr of partitions in IPT
467; for each partition get LVM drive-letter and reset bit in map.
468
469LVM_ComposeFreeDriveletterMap EndP
470
Note: See TracBrowser for help on using the repository browser.