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

Last change on this file since 30 was 30, checked in by Ben Rietbroek, 14 years ago

AiR-BOOT v1.07 -- As released with eCS v2.1. [2011-05-06]
Signature-date: 2006-03-13. (incorrect)
Trunk contains buildable v1.07 version as distributed with eCS v2.1.
Directory 'tags' contains v1.06 & v1.07 reference versions
built for all languages. Note that language ID for 'Dutch' changed
from 'DT' to 'NL' in v1.07 and that the v1.06 reference version also
uses 'NL' for 'Dutch'.
Also note that helper programs like the installer and setaboot are
are only modified for the OS/2 versions in v1.07.
The signature-date for v1.07 incorrectly states the same
date as for v1.06. The signature-version is correct.
Removed other binaries. (cd-rom images, old releases, etc.)
The tags serve as reference versions:

  • v1.06: rebuilt from source. (tags/v1.06r)
  • v1.07: built as released with eCS v2.1. (tags/v1.07r)
File size: 17.5 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 ModuleNames
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 si di
191 mov cx, 11
192 repe cmpsb ; Compare total 11-bytes
193 pop di si cx
194 je LSKN_Found
195 add di, LocIPT_LenOfIPT
196 dec cl
197 jnz LSKN_SearchLoop
198 jmp LSKN_NotFound
199
200 LSKN_Found:
201 mov si, di
202 sub si, LocIPT_Name ; Back to Base-Pointer
203 call PART_GetPartitionNumber ; Get Number of Entry at [SI]
204 LSKN_NotFound:
205 ret
206LINUX_SearchKernelName EndP
207
208Linux_FuzzyString db 'Linux Boot - Alpha', 13, 10, 0
209Linux_GotBadKernel db ' - Bad Kernel/Bad FAT-16 partition', 0
210Linux_INT15error db ' - INT 15 error', 0
211Linux_RootDefine db 'root='
212
213LINUX_LoadKernel Proc Near Uses ; Direct Jump, No Preserves
214 ; TranslateToDev needs UNFILTERED Partition Pointers...
215 call PART_CalculateStraightPartPointers
216 push si
217 mov si, offset Linux_FuzzyString
218 call MBR_Teletype
219 pop si
220 ; DX - Starting-Cluster of Linux Kernel File
221 mov dx, ds:[si+LocIPT_LocationBegin]
222 ; from now on, we don't need si anymore
223
224 ; Linux has 1 'BR' (which is crap) and some setup sectors
225 ; we load them at 9000:0, what a luck, we are at 8000:0 :-))
226 push ds es
227 mov ax, 9000h
228 mov es, ax
229 xor di, di
230 call FAT16_ReadCluster ; Load First Cluster (DX) to 9000:0
231 mov cl, bptr es:[01F1h] ; Setup sectors to load
232 inc cl ; Total sectors to load to 9000:0
233 jmp LLL_CheckLeft
234
235 LLL_LoadSetupCodeLoop:
236 call FAT16_ReadCluster
237 LLL_CheckLeft:
238 sub cl, FAT16_SecsPerCluster
239 jz LLL_GotAllClusterDone
240 jc LLL_GotAllClusterNotEmpty
241 jmp LLL_LoadSetupCodeLoop
242
243 LLL_GotAllClusterDone:
244 xor cx, cx
245 jmp LLL_GotAll
246 LLL_GotAllClusterNotEmpty:
247 ; Damn, Cluster didn't got empty. So we have to copy the rest out...
248 xor ch, ch
249 not cl
250 inc cl ; 0FFh -> 1 sector to get...
251 ; Now copy rest to 6000:0 location for later processing...
252 ; ES:DI - Ending location of Setup Code
253 mov ax, 9000h
254 mov ds, ax
255 mov ax, 6000h
256 mov es, ax
257 push cx si ; Push Kernel-Entry-Pointer
258 mov si, di
259 shl cx, 9 ; Sectors to Byte Count
260 sub si, cx ; DS:SI - Begin of Kernel Data
261 xor di, di
262 shr cx, 1
263 rep movsw ; Copy Data...
264 pop si cx ; Get Kernel-Entry-Pointer back
265 LLL_GotAll:
266 pop es ds
267
268 push cx dx ; Push Missing-Sectors, StartCluster
269 mov ax, 9000h
270 mov ds, ax
271
272 ; Check Signatures for security...
273 cmp wptr ds:[1FEh], 0AA55h
274 jne LLL_BadKernel
275 cmp wptr ds:[202h], 'dH'
276 jne LLL_BadKernel
277 cmp wptr ds:[204h], 'Sr'
278 je LLL_GoodKernel
279 LLL_BadKernel:
280 push es
281 pop ds
282 mov si, offset Linux_GotBadKernel
283 call MBR_Teletype
284 jmp MBR_HaltSystem
285 LLL_GoodKernel:
286
287 ; Now we have at least some of the required sectors loaded
288 mov ax, 9000h
289 mov dx, ax
290 mov al, bptr ds:[01F1h] ; Setup Sectors to load
291 ; -> to 9020:0
292
293 ; Just append parameters to end of Linux boot-block...
294 xor ah, ah
295 mov bl, 20h
296 mul bl ; AX * 20
297 add dx, ax ; add to segment -> Segment of Parameters
298
299 mov wptr ds:[0020h], 0A33Fh
300 mov ax, dx
301 and ax, 0FFFh ; 9100h -> 0100h
302 shl ax, 4 ; 0100h -> 1000h
303 mov wptr ds:[0022h], ax ; offset of parameter relative 9000:0
304
305 ; fill out Linux-Loader byte, so SETUP will do its job
306 mov bptr ds:[0210h], 0A0h ; AiR-BOOT (unknown ID for Linux btw)
307 mov cx, wptr ds:[01F4h] ; Linux Kernel Length in 16-byte blocks
308 shr cx, 5
309 inc cx ; Convert to Sector-Count
310 push cx
311 push cs
312 pop ds ; CS == DS
313 mov es, dx ; ES = Segment for parameters
314 xor di, di ; ES:0 - Parameter Ptr
315 mov dl, cs:[CFG_LinuxRootPartition]
316 cmp dl, 0FFh
317 je LLL_NoRootPartitionFound
318 mov cx, 5
319 mov si, offset Linux_RootDefine
320 rep movsb ; root=
321 call LINUX_TranslateToDEV ; Writes DEV (dl) at ES:DI (/dev/hda9)
322
323 LLL_NoRootPartitionFound:
324 ; Root-Define complete, now for the user Kernel Command-Line...
325 mov si, offset CFG_LinuxCommandLine
326 mov al, ds:[si]
327 or al, al
328 jz LLL_CommandLineLoop
329 mov al, ' '
330 stosb ; If any command-line, insert space
331 LLL_CommandLineLoop:
332 lodsb
333 stosb ; Copy string till and including NUL
334 or al, al
335 jnz LLL_CommandLineLoop
336 stosb ; Write another NUL
337 pop cx
338 pop dx bx ; Pop StartCluster, Missing-Sectors
339 ; CX - Sector-Count of Kernel Image, DX - Starting Cluster of Kernel Image
340 ; BX - Sector-Count left over in 6000:0 area from Setup Code loading
341 ; DS == CS
342
343 ; Now comes some tricky part. Hopefully we have a tiny kernel.
344 ; If we have a big kernel, we have to 'upload' it to PM-memory space.
345 test bptr ds:[0211h], 01h
346 jz LLL_LoadNormalKernel
347 jmp LLL_LoadBigKernel
348
349 LLL_LoadNormalKernel:
350 ; NORMAL KERNEL
351
352 ; Still UNSUPPORTED. This suxxs
353
354 LLL_LoadBigKernel:
355 ; BIG KERNEL - Oh no, we have to load all data to extended memory...
356 mov ax, 6000h
357 mov es, ax
358 shr ax, 4
359 ; Set Source to 06:0000
360 mov bptr cs:[MBR_Linux_GDT_Src+0], al
361 mov wptr cs:[MBR_Linux_GDT_Src+1], ax
362 xor si, si
363 or bx, bx ; No unfinished Cluster ?
364 jz LLL_LoadBigKernelLoop
365 push cx
366 mov cx, bx
367 shl cx, 8 ; Sectors to WORD Count
368 call LINUX_MoveKernelPart ; Copy Data to Extended Memory
369 pop cx
370 LLL_LoadBigKernelLoop:
371 push cx
372 ; DX - Current Cluster
373 ; CX - Total WORDs that need to be loaded
374 ; ES - Segment
375 mov cx, 8000h
376 call LINUX_LoadDataToMemory
377 ; CX - Total WORDs that were loaded...
378 ; Got 6000:0 filled...
379 call LINUX_MoveKernelPart
380 shr cx, 8 ; WORDs to SEGMENTs
381 add si, cx
382 pop cx
383 cmp si, cx
384 jb LLL_LoadBigKernelLoop
385
386 LLL_FinishedLoadKernel:
387 ; either way, we give execution to setup at 9020:0
388 mov ax, 09020h
389 mov ss, ax
390 mov sp, 4000h-12h ; Linux wants it this way...
391 mov ds, ax
392 mov es, ax
393 db 0EAh
394 dw 0
395 dw 09020h
396LINUX_LoadKernel EndP
397
398; Loads Data from Cluster(s) to memory...
399; In: DX - First cluster to read from...
400; CX - Total WORDs that need to be loaded at least
401; ES - Segment, where to load to (Starting Offset is zero)
402; Out: CX - Total WORDs that got loaded
403; DX - Cluster following last loaded cluster
404; (buffer filled)
405; Destroyed: None
406; MUST BE USING CS for addressing Code Segment, DS =! CS
407LINUX_LoadDataToMemory Proc Near Uses di
408 shl cx, 1 ; Convert WORDs to BYTEs
409 dec cx ; 0000h -> FFFFh
410 xor di, di
411 LLDTM_LoadLoop:
412 call FAT16_ReadCluster ; Load Cluster DX to ES:DI
413 ; DX and DI were updated by ReadCluster, so don't modify them...
414 or di, di
415 jz LLDTM_Overflow
416 cmp di, cx
417 jbe LLDTM_LoadLoop
418 mov cx, di
419 shr cx, 1
420 inc cx ; 3FFFh -> 4000h
421 ret
422 LLDTM_Overflow:
423 mov cx, 08000h
424 ret
425LINUX_LoadDataToMemory EndP
426
427; Copies Extended-Memory (clobbered from Linux setup)
428; In: CX - Total WORDs to copy
429; Out: (buffer copied)
430; Destroyed: None
431; MUST BE USING CS for addressing Code Segment, DS =! CS
432LINUX_MoveKernelPart Proc Near Uses ax cx es si
433 mov ax, cs
434 mov es, ax
435 mov si, offset MBR_Linux_GDT
436 push cx
437 mov ax, 08700h
438; IFDEF ReleaseCode
439 int 15h
440 jc LMKP_Error
441; ENDIF
442 pop cx
443 ; now adjust Destination by copied word-count
444 add wptr cs:[MBR_Linux_GDT_Dst], cx
445 adc bptr cs:[MBR_Linux_GDT_Dst+2], 0
446 add wptr cs:[MBR_Linux_GDT_Dst], cx
447 adc bptr cs:[MBR_Linux_GDT_Dst+2], 0
448 ret
449 LMKP_Error:
450 mov ax, cs
451 mov ds, ax
452 mov si, offset Linux_INT15error
453 call MBR_Teletype
454 jmp MBR_HaltSystem
455LINUX_MoveKernelPart EndP
456
457MBR_Linux_GDT: dw 0, 0, 0, 0
458 dw 0, 0, 0, 0
459 dw 0FFFFh
460MBR_Linux_GDT_Src db 0, 0, 06h ; Source is 6000:0
461 db 093h
462 dw 0
463 dw 0FFFFh
464MBR_Linux_GDT_Dst db 0, 0, 10h ; Dest is "10000:0"
465 db 093h
466 dw 0
467 dw 0, 0, 0, 0
468 dw 0, 0, 0, 0
469 dw 0
470
471;
472; Example of boot setup command under lilo prompt:
473;
474; lilo: linux root=/dev/sda2 sym53c8xx=tags:4,sync:10,debug:0x200
475;
Note: See TracBrowser for help on using the repository browser.