source: trunk/BOOTCODE/SPECIAL/LVM.ASM@ 46

Last change on this file since 46 was 46, checked in by Ben Rietbroek, 12 years ago

Various Changes [2012-04-14]

WARNING!!

All commits upto and including the commit of [2012-05-13] contain
a severe bug!! Building from these sources and then disabling
the 'force LBA' feature while also using the drive-letter feature or
editing the label can DESTROY THE MBR on ALL ATTACHED DISKS!!
DO NOT DISABLE 'FORCE LBA USAGE' WHEN BUILT FROM THE THESE COMMITS!!

Changes

o Added BLDLEVEL support
o Enhanced Master Make
o Sanitized sources
o Support for Wasm and Masm6 (experimental)
o Renamed MBR_PROT.ASM to MBR-PROT.ASM
o Merged bitfield code Into Installer
o First steps for cross platform Installer
o More...

File size: 13.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 ModuleNames
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
35 xor dx, dx ; DX:AX - CRC-Value
36 mov ch, 8
37 LVM_ICRCT_Loop2:
38 shr dx, 1
39 rcr ax, 1 ; Shift value 1 to the right
40 jnc LVM_ICRCT_NoXOR
41 xor dx, 0EDB8h
42 xor ax, 8320h
43 LVM_ICRCT_NoXOR:
44 dec ch
45 jnz LVM_ICRCT_Loop2
46 mov wptr [di+0], ax
47 mov wptr [di+2], dx
48 add di, 4
49 add cl, 1
50 jnc LVM_ICRCT_Loop
51 ret
52LVM_InitCRCTable EndP
53
54; Calculates an LVM-Sector CRC of a given sector
55; In: DS:SI - Points to Sector...
56; Out: DX:AX - LVM CRC
57; Destroyed: None
58LVM_GetSectorCRC Proc Near Uses bx cx
59 push wptr [si+LocLVM_CRC]
60 push wptr [si+LocLVM_CRC+2]
61 push si
62 mov wptr [si+LocLVM_CRC], 0
63 mov wptr [si+LocLVM_CRC+2], 0
64 mov ax, -1
65 mov dx, -1
66 mov cx, 512
67 LVM_GSCRC_Loop:
68 xor bh, bh
69 mov bl, al ; Save last byte to BL
70 mov al, ah
71 mov ah, dl
72 mov dl, dh
73 xor dh, dh ; SHR DX:AX, 8
74 xor bl, [si]
75 inc si ; XOR last byte with [data]
76 shl bx, 1
77 shl bx, 1
78 xor ax, wptr [LVM_CRCTable+bx+0]
79 xor dx, wptr [LVM_CRCTable+bx+2] ; XOR with CRC-Table
80 loop LVM_GSCRC_Loop
81 pop si
82 pop wptr [si+LocLVM_CRC+2]
83 pop wptr [si+LocLVM_CRC]
84 ret
85LVM_GetSectorCRC EndP
86
87; Checks ds:[SI], if a valid LVM Signature is found (sets carry in that case)
88; This does not check for valid LVM CRC (which also needs to be done)
89; In: DS:SI - Sector that needs to get checked...
90; Out: Carry set, if valid LVM signature found
91; Destroyed: None
92LVM_CheckSectorSignature Proc Near
93 test byte ptr [CFG_IgnoreLVM], 1 ; We are supposed to ignore LVM, so
94 jnz LVMCSS_InvalidSignature ; any sector is bad!
95 cmp word ptr [si+LocLVM_SignatureStart], 5202h ; Rousseau: identify LVM sector
96 jne LVMCSS_InvalidSignature
97 cmp word ptr [si+LocLVM_SignatureStart+2], 'BM'
98 jne LVMCSS_InvalidSignature
99 cmp word ptr [si+LocLVM_SignatureStart+4], 'MP'
100 jne LVMCSS_InvalidSignature
101 cmp word ptr [si+LocLVM_SignatureStart+6], 'DF'
102 jne LVMCSS_InvalidSignature
103 stc
104 ret
105 LVMCSS_InvalidSignature:
106 clc
107 ret
108LVM_CheckSectorSignature EndP
109
110; Checks Sector for a valid LVM CRC is encountered
111; First one should check for a valid signature and call this later.
112; In: DS:SI - Sector that needs to get checked...
113; Out: Carry set, if LVM CRC valid
114; Destroyed: None
115LVM_CheckSectorCRC Proc Near Uses ax dx
116 call LVM_GetSectorCRC
117 cmp ax, word ptr [si+LocLVM_CRC]
118 jne LVMCSCRC_BadCRC
119 cmp dx, word ptr [si+LocLVM_CRC+2]
120 jne LVMCSCRC_BadCRC
121 stc
122 ret
123 LVMCSCRC_BadCRC:
124 clc
125 ret
126LVM_CheckSectorCRC EndP
127
128; Updates Sector with valid LVM CRC
129; This one doesn't check, if it's really an LVM sector, so check before!
130; In: DS:SI - Sector that needs to get checked...
131; Out: None, CRC updated
132; Destroyed: None
133LVM_UpdateSectorCRC Proc Near Uses ax dx
134 call LVM_GetSectorCRC
135 mov word ptr [si+LocLVM_CRC], ax
136 mov word ptr [si+LocLVM_CRC+2], dx
137 ret
138LVM_UpdateSectorCRC EndP
139
140; Searches for a partition in LVM Information Sector and sets SI to point to
141; the LVM-entry. It will also set CARRY then.
142; In: DX:AX - LBA starting sector of partition to be searched
143; DS:SI - Valid (previously checked) LVM-Information-Sector
144; Out: Carry set, if partition found
145; DS:SI - points to LVM information entry
146; Destroyed: None
147LVM_SearchForPartition Proc Near Uses cx
148 cmp bptr [si+LocLVM_SignatureStart], LocLVM_SignatureByte0
149 jne LVMSFP_NotFound ; Quick Check, if LVM sector there
150 add si, LocLVM_StartOfEntries
151 mov cl, LocLVM_MaxEntries
152 LVMSFP_Loop:
153 cmp ax, [si+LocLVM_PartitionStart]
154 jne LVMSFP_NextEntry
155 cmp dx, [si+LocLVM_PartitionStart+2]
156 je LVMSFP_FoundIt
157 LVMSFP_NextEntry:
158 add si, LocLVM_LenOfEntry
159 dec cl
160 jnz LVMSFP_Loop
161 LVMSFP_NotFound:
162 clc
163 ret
164 LVMSFP_FoundIt:
165 stc
166 ret
167LVM_SearchForPartition EndP
168
169
170; Gets a drive-letter from the LVM-info of a partition. (if it exists)
171; In: BX:CX - LBA starting sector of partition to be searched
172; DL = Physical Disk in BIOS notation. (80h+)
173; Out: Carry set, if LVM-info found
174; AL - drive-letter from LVM-info
175
176LVM_GetDriveLetter Proc Near Uses bx cx dx si di ds es
177 ; For primary partitions this information is stored in the last
178 ; sector of track0; for all four partition entries in case they
179 ; they are all primary ones.
180 ;
181 ; LVM DLAT info for logical partitions is stored in the sector
182 ; preceding the start of the partition.
183 ;
184 ; Because the LVM info of a logical partition is the easiest to find,
185 ; we do that first. The LVM info for primary partitions is located
186 ; dependent on the geometry in use, so we use a special locater
187 ; call for that. Also, since the LVM info for primaries contains
188 ; info on all 4 entries, we need the partition index to obtain the
189 ; correct drive-letter.
190 ;
191
192 ; See if this is a primary partition
193 ; CY will be set if it is and AL will contain the 0-based
194 ; index in the P-table.
195 ; If it's a logical partition, CY will be clear and AL
196 ; will be set to 0ffh indicating an invalid index.
197 call PART_IsPrimaryPartition
198 mov al,0
199 rcl al,1 ; CY if primary
200 mov dh,al ; Save PRI or LOG
201
202 ; Save PRI/LOG indicator for later use
203 push dx
204
205 ; Load *possible* LVM sector
206 ; This load is only valid if the partition is logical, in which case
207 ; the LVM sector is below the start of the partition.
208 ; If primary, the LVM sector is at a location that
209 ; DriveIO_LoadMasterLVMSector will find out.
210
211 ; Push LBA address
212 push bx
213 push cx
214
215 ; Adjust for logical LVM-sector
216 sub cx,1
217 sbb bx,0
218
219 ; Load the LVM sector
220 push si
221 push di
222 mov si,offset [LVMSector]
223 mov di,ds
224 call DriveIO_LoadSectorLBA
225 pop di
226 pop si
227
228 ; Restore LBA address
229 pop cx
230 pop bx
231
232 ; Restore PRI/LOG partition indicator in DH
233 pop dx
234
235 ; Test PRI or not
236 test dh,dh
237 ; It's not a PRI so we can use the previously loaded LVM sector
238 jz LVM_GetDriveLetter_is_not_pri
239
240 ; It's a PRI so we use the special locator function.
241 ; This locator takes care of extended eCS geometry should that be used
242 call DriveIO_LoadMasterLVMSector
243
244 LVM_GetDriveLetter_is_not_pri:
245
246
247 ;
248 ; At this stage the LVM-info sector has been loaded at [LVMSector].
249 ; From here we look for an LVM entry for the partition.
250 ; If one is found, based on it's LBA-start, it's driveletter is used
251 ; in case byte 25h in the BPB is zero.
252 ;
253
254
255 ; Search for the partition in the LVM info.
256 ; If found, CY is set and SI points to LVM entry.
257 push si
258 mov ax,cx
259 mov dx,bx
260 mov si,offset [LVMSector]
261 call LVM_SearchForPartition
262 mov bx,si ; BX now points to LVM entry
263 mov dx,0 ; Setup null driveletter
264 pop si
265
266 mov al,0
267 ; Oops, no valid LVM record was used so we have a null driveletter.
268 jnc LVM_GetDriveLetter_null_lvm_dl
269
270 ;
271 ; At this point BX points to the LVM-entry related to the
272 ; partition, whether it was a logical or a primary one.
273 ;
274 mov al,[bx+LocLVM_VolumeLetter]
275 ; Clear CY if 0
276 test al,al
277 clc
278 jz LVM_GetDriveLetter_null_lvm_dl
279 stc
280
281 LVM_GetDriveLetter_null_lvm_dl:
282 ret
283LVM_GetDriveLetter EndP
284
285
286; Removes a given drive-letter from the whole LVM information sector
287; In: CH - drive-letter (ascii)
288; DS:SI - LVM-Information-Sector
289; Out: LVM-Information-Sector updated (including LVM CRC)
290; Destroyed: None
291LVM_RemoveVolLetterFromSector Proc Near Uses cx
292 cmp bptr [si+LocLVM_SignatureStart], LocLVM_SignatureByte0
293 jne LVMRVLFS_Done ; Quick Check, if LVM sector there
294 push si
295 add si, LocLVM_StartOfEntries
296 mov cl, LocLVM_MaxEntries
297 LVMRVLFS_Loop:
298 cmp ch, [si+LocLVM_VolumeLetter]
299 jne LVMRVLFS_NextEntry
300 ; Reset drive-letter, if matched
301 mov bptr [si+LocLVM_VolumeLetter], 0
302 LVMRVLFS_NextEntry:
303 add si, LocLVM_LenOfEntry
304 dec cl
305 jnz LVMRVLFS_Loop
306 pop si
307 call LVM_UpdateSectorCRC
308 LVMRVLFS_Done:
309 ret
310LVM_RemoveVolLetterFromSector EndP
311
312; Reassigns LVM volume driveletter
313; Will remove the drive-letter from any volume that got it currently
314; and finally change the drive-letter of the given partition
315; In: AL - drive-letter
316; DS:SI - points to partition, that needs that driveletter
317; Out: None
318; Destroyed: AX
319LVM_DoLetterReassignment Proc Near Uses bx cx dx si di
320 mov di, si ; Save SI in DI (Partition-pointer)
321 mov ch, al ; and AL in CH (drive-letter)
322 xor bx, bx
323 mov cl, CFG_Partitions
324 or cl, cl
325 jz LVMDLR_SkipRemove
326 LVMDLR_RemoveLoop:
327 cmp bptr [PartitionVolumeLetters+bx], ch
328 jne LVMDLR_NextPartition
329 ; One volume that has our wanted drive-letter, so remove it!
330 mov dl, bl
331 call PART_GetPartitionPointer ; DL - partition -> SI
332 ; Now set CurPartition_Location for the DriveIO-functions to work
333 mov ax, wptr [si+LocIPT_AbsolutePartTable]
334 mov wptr [CurPartition_Location+0], ax
335 mov ax, wptr [si+LocIPT_AbsolutePartTable+2]
336 mov wptr [CurPartition_Location+2], ax
337 mov ax, wptr [si+LocIPT_LocationPartTable+1]
338 mov wptr [CurPartition_Location+6], ax
339 mov ah, bptr [si+LocIPT_LocationPartTable+0]
340 mov al, [si+LocIPT_Drive]
341 mov wptr [CurPartition_Location+4], ax
342 call DriveIO_LoadLVMSector ; SI points now to LVM-Sector
343 call LVM_RemoveVolLetterFromSector
344 IFDEF ReleaseCode
345 call DriveIO_SaveLVMSector ; Save sector
346 ENDIF
347 LVMDLR_NextPartition:
348 inc bx
349 dec cl
350 jnz LVMDLR_RemoveLoop
351 LVMDLR_SkipRemove:
352 ; Set CurPartition_Location information of destination partition
353 mov ax, wptr [di+LocIPT_AbsolutePartTable]
354 mov wptr [CurPartition_Location+0], ax
355 mov ax, wptr [di+LocIPT_AbsolutePartTable+2]
356 mov wptr [CurPartition_Location+2], ax
357 mov ah, bptr [di+LocIPT_LocationPartTable+0]
358 mov al, [di+LocIPT_Drive]
359 mov wptr [CurPartition_Location+4], ax
360 mov ax, wptr [di+LocIPT_LocationPartTable+1]
361 mov wptr [CurPartition_Location+6], ax
362 call DriveIO_LoadLVMSector ; SI points now to LVM-Sector
363 mov ax, wptr [di+LocIPT_AbsoluteBegin]
364 mov dx, wptr [di+LocIPT_AbsoluteBegin+2]
365 mov di, si ; Save SI in DI
366 call LVM_SearchForPartition
367 jnc LVMDLR_DestPartNotFound
368 ; Set new volume letter
369 mov bptr [si+LocLVM_VolumeLetter], ch
370 mov si, di ; SI - LVM Sector again
371 call LVM_UpdateSectorCRC ; Update LVM-CRC now
372 IFDEF ReleaseCode
373 call DriveIO_SaveLVMSector ; Save sector
374 ENDIF
375 LVMDLR_DestPartNotFound:
376 ; This here is done for safety, because we misuse CurPartition_Location
377 xor ax, ax
378 mov di, offset CurPartition_Location
379 mov cx, 4
380 rep stosw ; NUL out CurPartition_Location
381 ret
382LVM_DoLetterReassignment EndP
Note: See TracBrowser for help on using the repository browser.