source: trunk/BOOTCODE/SPECIAL/LINUX.ASM@ 54

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

AiR-BOOT v1.0.8-rc3 build-20120909 [2012-09-10]

With Git one can easily hop-skip-and-jump between branches.
So I use Git for my local repos and make use of this easy branching.
Because SVN can only handle lineair history, these branches had to be
rebased before committing them to Netlabs. So, this commit contains a
multitude of changes which makes it a bit hairy.

New

o Display LVM drive-letters in the main menu

A populair request was to show drive-letter information in the menu.
Drive-letters however, are OS specific and AiR-BOOT cannot
accurately predict what drive-letter other operating systems would
assign to what partition. eCS LVM drive-letters however are stored
in the LVM-record and can thus be displayed.

o Added 'Show LVM Drive Letters' option in SETUP/BASIC

This will toggle the display of LVM drive-letters in the main menu.
By default this option is enabled.

o Show popup message when BIOS INT13X extensions are not available

The system is halted.

o Show 'DEL to Power Off' in the bottom left corner

This tries to power-off the system, but it may not work for you.

o Simple interactive debugger

Outputs to the serial port with a few one-letter commands to dump
internal tables and state. (Only available in debug builds)

o Enhanced drive-letter feature

Enable multiple eCS installations using the same drive-letter.
This makes it possible to clone a system with the command
'XCOPY /h /o /t /s /e /r /v /e' to another drive and have that boot
from the same drive-letter.
(Or installing to the same drive by hiding the other system)

Changes

o Reduced MBR protection-image from 1024 to 768 bytes

Luckily the MBR Protection Image code does not exceed 768 bytes,
so that gives us another 256 bytes of precious code-space.
Now the non-EN versions are happy again.
Note that the alignment for the image changed from 512 to 256 bytes.
MBR-PROT.ASM, FIXCODE.C, PARTMAIN.ASM and AIR-BOOT.ASM have been
adjusted for this change.
The fight for code-space continues...

o Updating from v1.06 now also copies over drive-letters

When the user has forced drive-letters in v1.06 these will be copied
over to the v1.0.8 configuration when upgrading.
Because the drive-letter feature is broken in v1.07,
the drive-letter table does not get copied over when upgrading
from v1.07.

o Made FX-code optional to compile in

The FX-code supplies the shifting screen-effects when 'Cooper Bars'
is enabled in the setup. With the current enhancements made however,
there is a continuous lack of code-space, especially when debug-code
is included during development. The FX-code occupies some
1200 bytes, a space that can be put to better use. Therefore the
inclusion of the FX-code has been made conditional to make room for
either debugging or future new features.

o Also rewrite PBR on HPFS

Earlier, a fix was made to write a modified PBR back in case JFS was
used. This was done to enable the drive-letter feature on JFS, since
the PBR JFS-bootcode does not use the supplied PBR in memory.
With the enhancements in the drive-letter feature, the HPFS PBR
needs to be updated on disk also, to cope with zero drive-letters in
the HPFS PBR. This potentially fixes a missing drive-letter in the
PBR when the system is restored from an archive. You might need the
drive-letter feature to force the correct drive-letter on the first
boot, after which the feature can be disabled.

o Added extra MBR protection

When AiR-BOOT is active, it is only AiR-BOOT that writes to the MBR.
To protect the MBR from programming errors, like the one below,
any write to the MBR is now checked for validity.
In essence this is protecting your MBR from bad programming done
by me...

Fixes

o Fixed a minor bug with displaying LVM drive-letters

When more partitions that can be displayed were present, scrolling
the menu would not scroll the drive-letter. Fixed.

o Fixed a bug with regard to the drive-letter feature

When partitions were deleted, and some partitions above the deleted
partition(s) had a drive-letter forced, these partitions would lose
this assignment. This bug is also present in v1.06.

Note

The AIRBOOT.HIS file mentions a DOCU directory with the AiR-BOOT
documentation etc. However, this is not present in this commit and
will be provided at a later time.

File size: 17.6 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 / LINUX SUPPORT
20;---------------------------------------------------------------------------
21
22; Here is the startup-code for Linux-Kernels. I'm sure this won't work on
23; all of them, but on the latest.
24
25; Note: This code will ONLY WORK on computers with INT 13h Extension.
26; I did not want to code silly cylinder stuff here and if you don't
27; have INT 13h Extensions, you will not need this. LINUXIMG won't work
28; without them.
29;
30; And another note: *F**k* Linux usenet-users. Really. I mean *f**k them*.
31; I asked in an OS/2 newsgroup for testers -> Got 8 volunteers within some
32; days. I asked in 2 Linux newsgroups. What did happen? Some idiots discussed
33; the whole sh*t with me, knew nothing about INT13h CHS/LBA mode, BIOS,
34; boot-managers in general, assembly coding and other stuff and wanted to tell
35; me that 95k GRUB is well-coded and its good to have it placed all over your
36; harddrive and that file-support and all those lousy features would waste
37; sooo much space. ROFLMAO.
38;
39; I could implement some more file-systems into AiR-BOOT, but instead I did
40; some nice menus, setup, text, cyrillic support, demo-coder effects, easy
41; handling, help, auto-detection and plenty of other stuff INTO AROUND 25k.
42;
43; Oh, why is this code here? Because of 2 friends of mine. Otherwise I wouldnt
44; have done it as well as fat16.asm.
45
46IFDEF MODULE_NAMES
47DB 'LINUX',0
48ENDIF
49
50Linux_TranslateBase db '/dev/hd'
51Linux_KernelDirectory db 'KERNELS '
52
53; Translates partition-number to Linux-device name (e.g. /dev/hda3)
54; In: DL - partition number, ES:DI - destination 9-byte buffer
55; Out: (buffer filled)
56; Destroyed: None
57LINUX_TranslateToDEV Proc Near Uses eax ebx cx dx ds si
58 ; Damn Linux. Our logic is as follows: first get the drive letter.
59 ; that's easy. Now search our partition-table for new
60 ; extended partitions and fix them up. Stupid logic.
61 push cs
62 pop ds ; CS == DS
63 mov si, offset Linux_TranslateBase
64 mov cx, 7
65 rep movsb ; First write base-name (/dev/hd)...
66 ; First get our partition-table
67 call PART_GetPartitionPointer ; Partition (DL) -> CS:SI
68 mov dl, ds:[si+LocIPT_Drive]
69 mov al, dl
70 sub al, 1Fh ; Generate letter from drive (80h -> 61h)
71 stosb ; write letter
72
73 ; Now get the linux local partition number
74 ; 1. Search for partition, where TranslateDrive (DL) got used first
75 mov cx, si ; CX - Searched partition offset
76 mov si, offset PartitionTable ; begin here
77 LTTD_SearchDriveLoop:
78 cmp ds:[si+LocIPT_Drive], dl
79 je LTTD_SearchDrive_Found
80 add si, LocIPT_LenOfIPT
81 jmp LTTD_SearchDriveLoop
82 LTTD_SearchDrive_Found:
83 ; Now count all partitions to hit. After root partition set counter to
84 ; 4 and count further.
85 xor dh, dh ; Linux Partition Counter (Base 0)
86 LTTD_SearchPart_Loop:
87 inc dh ; Increase Linux Local Partition Number
88 mov ax, wptr ds:[si+LocIPT_AbsolutePartTable+2]
89 shr eax, 16
90 mov ax, wptr ds:[si+LocIPT_AbsolutePartTable+0] ; -> EAX
91 cmp dh, 4 ; over root partition yet ?
92 ja LTTD_ContinueLoop ; yes, continue loop
93 cmp eax, 0 ; not in root partition anymore?
94 je LTTD_ContinueLoop
95 mov dh, 5 ; nope, so adjust counter
96 LTTD_ContinueLoop:
97 cmp si, cx
98 je LTTD_SearchPart_Found
99 add si, LocIPT_LenOfIPT ; Next Partition
100 jmp LTTD_SearchPart_Loop
101
102 LTTD_SearchPart_Found:
103 or eax, eax
104 jnz LTTD_SearchPart_NotRootPartition
105 ; Bullshit, it's in the MBR, so we have to look for the
106 ; partition number directly (because EXTEND, EXT2: EXT2 would be
107 ; partition 1, in fact it would be partition 2)
108 ; All we do here is to load the MBR to memory (suck) and look in it
109 ; manually. Pervertly this could be crazy, when user
110 ; is in setup and changing 'Linux Root'.
111 mov ax, wptr ds:[si+LocIPT_AbsoluteBegin+2]
112 shr eax, 16
113 mov ax, wptr ds:[si+LocIPT_AbsoluteBegin+0] ; -> EAX
114 push eax
115 xor ax, ax
116 xor bx, bx
117 mov cx, 1
118 xor dh, dh
119 mov si, offset TmpSector
120 call DriveIO_LoadSector ; Load fucking MBR
121 pop eax
122 xor dh, dh ; Reset again to zero
123 add si, 446
124 LTTD_SearchRoot_Loop:
125 cmp bptr ds:[si+4], 0
126 je LTTD_SearchRoot_NoPart ; if partition...
127 inc dh ; add one
128 LTTD_SearchRoot_NoPart:
129 mov bx, wptr ds:[si+10]
130 shr ebx, 16
131 mov bx, wptr ds:[si+08] ; -> EBX (Start Sector)
132 add si, 16
133 cmp eax, ebx
134 jne LTTD_SearchRoot_Loop
135
136 LTTD_SearchPart_NotRootPartition:
137 mov al, dh
138 ; Now convert that crap (AL) to ascii and write it
139 cmp al, 10
140 jb LTTD_Smaller10
141 xor ah, ah
142 mov dl, 10
143 div dl
144 add al, 30h ; Generate number from value 00h -> 30h)
145 stosb
146 mov al, ah
147 LTTD_Smaller10:
148 add al, 30h ; Generate number from value
149 stosb
150 ret
151LINUX_TranslateToDEV EndP
152
153LINUX_InitFAT16access Proc Near Uses es
154 mov dl, ds:[CFG_LinuxKrnlPartition]
155 call PART_GetPartitionPointer ; Partition DL -> SI
156 call FAT16_InitAccess
157
158 call FAT16_ReadRoot
159
160 mov cx, FAT16_NumOfRootEntries
161 mov si, offset Linux_KernelDirectory
162 call FAT16_SearchEntry ; Fills up DX as Cluster-No
163 or dx, dx
164 jz LIFAT16A_NoDirectory
165
166 mov ax, 9000h
167 mov es, ax
168 xor di, di ; Read Cluster DX to 9000:0 (ES:DI)
169 call FAT16_ReadCluster
170 mov ax, cs
171 mov es, ax ; DS == ES == CS
172 call FAT16_ProcessKrnlDirectory
173
174 LIFAT16A_NoDirectory:
175 ret
176LINUX_InitFAT16access EndP
177
178; Initialize FAT-16 access on specified partition (required for following xs)
179; In: DS:SI - 11-Byte Kernel Name to search
180; Out: DL - FFh - if not found, otherwise the entry no is replied
181; Destroyed: None
182LINUX_SearchKernelName Proc Near Uses cx di
183 mov dl, 0FFh ; Nothing found is default...
184 mov cl, LINUX_KernelNo
185 or cl, cl
186 jz LSKN_NotFound
187 mov di, offset LINUX_KernelEntries
188 add di, LocIPT_Name
189 LSKN_SearchLoop:
190 push cx
191 push si
192 push di
193 mov cx, 11
194 repe cmpsb ; Compare total 11-bytes
195 pop di
196 pop si
197 pop cx
198 je LSKN_Found
199 add di, LocIPT_LenOfIPT
200 dec cl
201 jnz LSKN_SearchLoop
202 jmp LSKN_NotFound
203
204 LSKN_Found:
205 mov si, di
206 sub si, LocIPT_Name ; Back to Base-Pointer
207 call PART_GetPartitionNumber ; Get Number of Entry at [SI]
208 LSKN_NotFound:
209 ret
210LINUX_SearchKernelName EndP
211
212Linux_FuzzyString db 'Linux Boot - Alpha', 13, 10, 0
213Linux_GotBadKernel db ' - Bad Kernel/Bad FAT-16 partition', 0
214Linux_INT15error db ' - INT 15 error', 0
215Linux_RootDefine db 'root='
216
217LINUX_LoadKernel Proc Near Uses ; Direct Jump, No Preserves
218 ; TranslateToDev needs UNFILTERED Partition Pointers...
219 call PART_CalculateStraightPartPointers
220 push si
221 mov si, offset Linux_FuzzyString
222 call MBR_Teletype
223 pop si
224 ; DX - Starting-Cluster of Linux Kernel File
225 mov dx, ds:[si+LocIPT_LocationBegin]
226 ; from now on, we don't need si anymore
227
228 ; Linux has 1 'BR' (which is crap) and some setup sectors
229 ; we load them at 9000:0, what a luck, we are at 8000:0 :-))
230 push ds
231 push es
232 mov ax, 9000h
233 mov es, ax
234 xor di, di
235 call FAT16_ReadCluster ; Load First Cluster (DX) to 9000:0
236 mov cl, bptr es:[01F1h] ; Setup sectors to load
237 inc cl ; Total sectors to load to 9000:0
238 jmp LLL_CheckLeft
239
240 LLL_LoadSetupCodeLoop:
241 call FAT16_ReadCluster
242 LLL_CheckLeft:
243 sub cl, FAT16_SecsPerCluster
244 jz LLL_GotAllClusterDone
245 jc LLL_GotAllClusterNotEmpty
246 jmp LLL_LoadSetupCodeLoop
247
248 LLL_GotAllClusterDone:
249 xor cx, cx
250 jmp LLL_GotAll
251 LLL_GotAllClusterNotEmpty:
252 ; Damn, Cluster didn't got empty. So we have to copy the rest out...
253 xor ch, ch
254 not cl
255 inc cl ; 0FFh -> 1 sector to get...
256 ; Now copy rest to 6000:0 location for later processing...
257 ; ES:DI - Ending location of Setup Code
258 mov ax, 9000h
259 mov ds, ax
260 mov ax, 6000h
261 mov es, ax
262 ; Push Kernel-Entry-Pointer
263 push cx
264 push si
265 mov si, di
266 shl cx, 9 ; Sectors to Byte Count
267 sub si, cx ; DS:SI - Begin of Kernel Data
268 xor di, di
269 shr cx, 1
270 rep movsw ; Copy Data...
271 ; Get Kernel-Entry-Pointer back
272 pop si
273 pop cx
274 LLL_GotAll:
275 pop es
276 pop ds
277
278 ; Push Missing-Sectors, StartCluster
279 push cx
280 push dx
281 mov ax, 9000h
282 mov ds, ax
283
284 ; Check Signatures for security...
285 cmp wptr ds:[1FEh], 0AA55h
286 jne LLL_BadKernel
287 cmp wptr ds:[202h], 'dH'
288 jne LLL_BadKernel
289 cmp wptr ds:[204h], 'Sr'
290 je LLL_GoodKernel
291 LLL_BadKernel:
292 push es
293 pop ds
294 mov si, offset Linux_GotBadKernel
295 call MBR_Teletype
296 jmp MBR_HaltSystem
297 LLL_GoodKernel:
298
299 ; Now we have at least some of the required sectors loaded
300 mov ax, 9000h
301 mov dx, ax
302 mov al, bptr ds:[01F1h] ; Setup Sectors to load
303 ; -> to 9020:0
304
305 ; Just append parameters to end of Linux boot-block...
306 xor ah, ah
307 mov bl, 20h
308 mul bl ; AX * 20
309 add dx, ax ; add to segment -> Segment of Parameters
310
311 mov wptr ds:[0020h], 0A33Fh
312 mov ax, dx
313 and ax, 0FFFh ; 9100h -> 0100h
314 shl ax, 4 ; 0100h -> 1000h
315 mov wptr ds:[0022h], ax ; offset of parameter relative 9000:0
316
317 ; fill out Linux-Loader byte, so SETUP will do its job
318 mov bptr ds:[0210h], 0A0h ; AiR-BOOT (unknown ID for Linux btw)
319 mov cx, wptr ds:[01F4h] ; Linux Kernel Length in 16-byte blocks
320 shr cx, 5
321 inc cx ; Convert to Sector-Count
322 push cx
323 push cs
324 pop ds ; CS == DS
325 mov es, dx ; ES = Segment for parameters
326 xor di, di ; ES:0 - Parameter Ptr
327 mov dl, cs:[CFG_LinuxRootPartition]
328 cmp dl, 0FFh
329 je LLL_NoRootPartitionFound
330 mov cx, 5
331 mov si, offset Linux_RootDefine
332 rep movsb ; root=
333 call LINUX_TranslateToDEV ; Writes DEV (dl) at ES:DI (/dev/hda9)
334
335 LLL_NoRootPartitionFound:
336 ; Root-Define complete, now for the user Kernel Command-Line...
337 mov si, offset CFG_LinuxCommandLine
338 mov al, ds:[si]
339 or al, al
340 jz LLL_CommandLineLoop
341 mov al, ' '
342 stosb ; If any command-line, insert space
343 LLL_CommandLineLoop:
344 lodsb
345 stosb ; Copy string till and including NUL
346 or al, al
347 jnz LLL_CommandLineLoop
348 stosb ; Write another NUL
349 pop cx
350 ; Pop StartCluster, Missing-Sectors
351 pop dx
352 pop bx
353 ; CX - Sector-Count of Kernel Image, DX - Starting Cluster of Kernel Image
354 ; BX - Sector-Count left over in 6000:0 area from Setup Code loading
355 ; DS == CS
356
357 ; Now comes some tricky part. Hopefully we have a tiny kernel.
358 ; If we have a big kernel, we have to 'upload' it to PM-memory space.
359 test bptr ds:[0211h], 01h
360 jz LLL_LoadNormalKernel
361 jmp LLL_LoadBigKernel
362
363 LLL_LoadNormalKernel:
364 ; NORMAL KERNEL
365
366 ; Still UNSUPPORTED. This suxxs
367
368 LLL_LoadBigKernel:
369 ; BIG KERNEL - Oh no, we have to load all data to extended memory...
370 mov ax, 6000h
371 mov es, ax
372 shr ax, 4
373 ; Set Source to 06:0000
374 mov bptr cs:[MBR_Linux_GDT_Src+0], al
375 mov wptr cs:[MBR_Linux_GDT_Src+1], ax
376 xor si, si
377 or bx, bx ; No unfinished Cluster ?
378 jz LLL_LoadBigKernelLoop
379 push cx
380 mov cx, bx
381 shl cx, 8 ; Sectors to WORD Count
382 call LINUX_MoveKernelPart ; Copy Data to Extended Memory
383 pop cx
384 LLL_LoadBigKernelLoop:
385 push cx
386 ; DX - Current Cluster
387 ; CX - Total WORDs that need to be loaded
388 ; ES - Segment
389 mov cx, 8000h
390 call LINUX_LoadDataToMemory
391 ; CX - Total WORDs that were loaded...
392 ; Got 6000:0 filled...
393 call LINUX_MoveKernelPart
394 shr cx, 8 ; WORDs to SEGMENTs
395 add si, cx
396 pop cx
397 cmp si, cx
398 jb LLL_LoadBigKernelLoop
399
400 LLL_FinishedLoadKernel:
401 ; either way, we give execution to setup at 9020:0
402 mov ax, 09020h
403 mov ss, ax
404 mov sp, 4000h-12h ; Linux wants it this way...
405 mov ds, ax
406 mov es, ax
407 db 0EAh
408 dw 0
409 dw 09020h
410LINUX_LoadKernel EndP
411
412; Loads Data from Cluster(s) to memory...
413; In: DX - First cluster to read from...
414; CX - Total WORDs that need to be loaded at least
415; ES - Segment, where to load to (Starting Offset is zero)
416; Out: CX - Total WORDs that got loaded
417; DX - Cluster following last loaded cluster
418; (buffer filled)
419; Destroyed: None
420; MUST BE USING CS for addressing Code Segment, DS =! CS
421LINUX_LoadDataToMemory Proc Near Uses di
422 shl cx, 1 ; Convert WORDs to BYTEs
423 dec cx ; 0000h -> FFFFh
424 xor di, di
425 LLDTM_LoadLoop:
426 call FAT16_ReadCluster ; Load Cluster DX to ES:DI
427 ; DX and DI were updated by ReadCluster, so don't modify them...
428 or di, di
429 jz LLDTM_Overflow
430 cmp di, cx
431 jbe LLDTM_LoadLoop
432 mov cx, di
433 shr cx, 1
434 inc cx ; 3FFFh -> 4000h
435 ret
436 LLDTM_Overflow:
437 mov cx, 08000h
438 ret
439LINUX_LoadDataToMemory EndP
440
441; Copies Extended-Memory (clobbered from Linux setup)
442; In: CX - Total WORDs to copy
443; Out: (buffer copied)
444; Destroyed: None
445; MUST BE USING CS for addressing Code Segment, DS =! CS
446LINUX_MoveKernelPart Proc Near Uses ax cx es si
447 mov ax, cs
448 mov es, ax
449 mov si, offset MBR_Linux_GDT
450 push cx
451 mov ax, 08700h
452; IFDEF ReleaseCode
453 int 15h
454 jc LMKP_Error
455; ENDIF
456 pop cx
457 ; now adjust Destination by copied word-count
458 add wptr cs:[MBR_Linux_GDT_Dst], cx
459 adc bptr cs:[MBR_Linux_GDT_Dst+2], 0
460 add wptr cs:[MBR_Linux_GDT_Dst], cx
461 adc bptr cs:[MBR_Linux_GDT_Dst+2], 0
462 ret
463 LMKP_Error:
464 mov ax, cs
465 mov ds, ax
466 mov si, offset Linux_INT15error
467 call MBR_Teletype
468 jmp MBR_HaltSystem
469LINUX_MoveKernelPart EndP
470
471MBR_Linux_GDT: dw 0, 0, 0, 0
472 dw 0, 0, 0, 0
473 dw 0FFFFh
474MBR_Linux_GDT_Src db 0, 0, 06h ; Source is 6000:0
475 db 093h
476 dw 0
477 dw 0FFFFh
478MBR_Linux_GDT_Dst db 0, 0, 10h ; Dest is "10000:0"
479 db 093h
480 dw 0
481 dw 0, 0, 0, 0
482 dw 0, 0, 0, 0
483 dw 0
484
485;
486; Example of boot setup command under lilo prompt:
487;
488; lilo: linux root=/dev/sda2 sym53c8xx=tags:4,sync:10,debug:0x200
489;
Note: See TracBrowser for help on using the repository browser.