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

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

Removed 'Force BIOS-LBA Usage' entry from AiR-BOOT SETUP [2012-05-15]

This commit eliminates the severe bug that previous commits warned
about in their commit-message. The cause of the bug is not handling
CHS values when modifying LVM-information. Thus, when LBA-access was
disabled, the CHS-access method was used with improper values. This
resulted in a CHS address of (0,0,1), which is the MBR, and then
erroneously writing the modified LVM-record to it.

While a freshly installed AiR-BOOT of v1.07 or higher defaults to having
LBA enabled, this is not the case for v1.06. Since AiR-BOOT merges the
previous configuration, any upgrade from v1.06 with LBA set to disabled
would propagate the setting to the new version. Modifying
LVM-information from the AiR-BOOT SETUP, like changing the label or
fiddling with drive-letter assignments, would then trigger the bug and
write the LVM-record to the MBR. Users fiddling with the SETUP could
also disable LBA-access and trigger the bug.

This commit removes the 'Force BIOS-LBA Usage' option from the
AiR-BOOT SETUP, preventing users to disable LBA. Also, when AiR-BOOT
starts, it now always enables LBA-addressing, so CHS-addressing is not
used anymore. Furthermore, the Installer is modified to always enable
LBA-addressing in the AiR-BOOT configuration it writes to disk.
This ensures that older versions, which do not implicitly enable LBA on
starting, will find LBA as enabled.

On today's systems there is no need to use CHS-addressing anymore.
In fact, it does more harm than good because the CHS values do not
represent true physical geometry anymore. Instead, the drive and
the BIOS do translations that can cause unpredictable results when
moving the drive between systems. This is particularly true for USB
mass storage devices.

Therefore, CHS-addressing will be removed from AiR-BOOT.
This will free-up badly needed code space and create some room in the
internal partition tables that can be put to other use.

Info

o Bug Description

Trashing the Master Boot Record.

o Cause

Not handling CHS values while modifying LVM-information.

o Effect

Writing the modified LVM-record to the MBR when modifying LVM
information from the AiR-BOOT SETUP.
(like the partition-label or drive-letter assignments)

o Measures

  • Remove 'Force BIOS-LBA Usage' from AiR-BOOT SETUP
  • Always enable LBA when AiR-BOOT starts
  • Always set LBA enabled when writing on-disk AiR-BOOT configuration

o Affected AiR-BOOT versions

*All* v1.0.8 pre-releases up and including commit [2012-05-13].

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
327 LVMDLR_RemoveLoop:
328 cmp bptr [PartitionVolumeLetters+bx], ch
329 jne LVMDLR_NextPartition
330 ; One volume that has our wanted drive-letter, so remove it!
331 mov dl, bl
332 call PART_GetPartitionPointer ; DL - partition -> SI
333 ; Now set CurPartition_Location for the DriveIO-functions to work
334 mov ax, wptr [si+LocIPT_AbsolutePartTable]
335 mov wptr [CurPartition_Location+0], ax
336 mov ax, wptr [si+LocIPT_AbsolutePartTable+2]
337 mov wptr [CurPartition_Location+2], ax
338 mov ax, wptr [si+LocIPT_LocationPartTable+1]
339 mov wptr [CurPartition_Location+6], ax
340 mov ah, bptr [si+LocIPT_LocationPartTable+0]
341 mov al, [si+LocIPT_Drive]
342 mov wptr [CurPartition_Location+4], ax
343 call DriveIO_LoadLVMSector ; SI points now to LVM-Sector
344 call LVM_RemoveVolLetterFromSector
345 IFDEF ReleaseCode
346 call DriveIO_SaveLVMSector ; Save sector
347 ENDIF
348 LVMDLR_NextPartition:
349 inc bx
350 dec cl
351 jnz LVMDLR_RemoveLoop
352
353 LVMDLR_SkipRemove:
354 ; Set CurPartition_Location information of destination partition
355 mov ax, wptr [di+LocIPT_AbsolutePartTable]
356 mov wptr [CurPartition_Location+0], ax
357 mov ax, wptr [di+LocIPT_AbsolutePartTable+2]
358 mov wptr [CurPartition_Location+2], ax
359 mov ah, bptr [di+LocIPT_LocationPartTable+0]
360 mov al, [di+LocIPT_Drive]
361 mov wptr [CurPartition_Location+4], ax
362 mov ax, wptr [di+LocIPT_LocationPartTable+1]
363 mov wptr [CurPartition_Location+6], ax
364 call DriveIO_LoadLVMSector ; SI points now to LVM-Sector
365 mov ax, wptr [di+LocIPT_AbsoluteBegin]
366 mov dx, wptr [di+LocIPT_AbsoluteBegin+2]
367 mov di, si ; Save SI in DI
368 call LVM_SearchForPartition
369 jnc LVMDLR_DestPartNotFound
370 ; Set new volume letter
371 mov bptr [si+LocLVM_VolumeLetter], ch
372 mov si, di ; SI - LVM Sector again
373 call LVM_UpdateSectorCRC ; Update LVM-CRC now
374 IFDEF ReleaseCode
375 call DriveIO_SaveLVMSector ; Save sector
376 ENDIF
377 LVMDLR_DestPartNotFound:
378 ; This here is done for safety, because we misuse CurPartition_Location
379 xor ax, ax
380 mov di, offset CurPartition_Location
381 mov cx, 4
382 rep stosw ; NUL out CurPartition_Location
383 ret
384LVM_DoLetterReassignment EndP
Note: See TracBrowser for help on using the repository browser.