source: trunk/bootcode/special/linux.asm@ 57

Last change on this file since 57 was 57, checked in by Ben Rietbroek, 10 years ago

All source-files lowercased [v1.1.1-testing]

Some standard files like 'COPYING', 'LICENSE', etc. have not been
converted to lower case because they are usually distributed uppercased.

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.