Contents of /tags/mkinitrd-6_2_0/isolinux/ui.inc
Parent Directory | Revision Log
Revision 996 -
(show annotations)
(download)
Sun May 30 11:54:28 2010 UTC (14 years, 4 months ago) by niro
File size: 13067 byte(s)
Sun May 30 11:54:28 2010 UTC (14 years, 4 months ago) by niro
File size: 13067 byte(s)
tagged 'mkinitrd-6_2_0'
1 | ;; $Id: ui.inc,v 1.1 2007-09-01 22:44:05 niro Exp $ |
2 | ;; ----------------------------------------------------------------------- |
3 | ;; |
4 | ;; Copyright 1994-2005 H. Peter Anvin - All Rights Reserved |
5 | ;; |
6 | ;; This program is free software; you can redistribute it and/or modify |
7 | ;; it under the terms of the GNU General Public License as published by |
8 | ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, |
9 | ;; Boston MA 02111-1307, USA; either version 2 of the License, or |
10 | ;; (at your option) any later version; incorporated herein by reference. |
11 | ;; |
12 | ;; ----------------------------------------------------------------------- |
13 | |
14 | ; |
15 | ; This file should be entered with the config file open (for getc) |
16 | ; |
17 | call parse_config ; Parse configuration file |
18 | no_config_file: |
19 | ; |
20 | ; Check whether or not we are supposed to display the boot prompt. |
21 | ; |
22 | check_for_key: |
23 | cmp word [ForcePrompt],0 ; Force prompt? |
24 | jnz enter_command |
25 | test byte [KbdFlags],5Bh ; Shift Alt Caps Scroll |
26 | jz auto_boot ; If neither, default boot |
27 | |
28 | enter_command: |
29 | cmp word [NoEscape],0 ; If NOESCAPE, no prompt, |
30 | jne auto_boot ; always run default cmd |
31 | |
32 | mov si,boot_prompt |
33 | call cwritestr |
34 | |
35 | mov byte [FuncFlag],0 ; <Ctrl-F> not pressed |
36 | mov di,command_line |
37 | |
38 | ; |
39 | ; get the very first character -- we can either time |
40 | ; out, or receive a character press at this time. Some dorky BIOSes stuff |
41 | ; a return in the buffer on bootup, so wipe the keyboard buffer first. |
42 | ; |
43 | clear_buffer: mov ah,11h ; Check for pending char |
44 | int 16h |
45 | jz get_char_time |
46 | mov ah,10h ; Get char |
47 | int 16h |
48 | jmp short clear_buffer |
49 | |
50 | ; For the first character, both KbdTimeout and |
51 | ; TotalTimeout apply; after that, only TotalTimeout. |
52 | |
53 | get_char_time: |
54 | mov eax,[TotalTimeout] |
55 | mov [ThisTotalTo],eax |
56 | mov eax,[KbdTimeout] |
57 | mov [ThisKbdTo],eax |
58 | |
59 | get_char: |
60 | call getchar_timeout |
61 | and dword [ThisKbdTo],0 ; For the next time... |
62 | |
63 | and al,al |
64 | jz func_key |
65 | |
66 | got_ascii: cmp al,7Fh ; <DEL> == <BS> |
67 | je backspace |
68 | cmp al,' ' ; ASCII? |
69 | jb not_ascii |
70 | ja enter_char |
71 | cmp di,command_line ; Space must not be first |
72 | je short get_char |
73 | enter_char: test byte [FuncFlag],1 |
74 | jz .not_ctrl_f |
75 | mov byte [FuncFlag],0 |
76 | cmp al,'0' |
77 | jb .not_ctrl_f |
78 | je ctrl_f_0 |
79 | cmp al,'9' |
80 | jbe ctrl_f |
81 | .not_ctrl_f: cmp di,max_cmd_len+command_line ; Check there's space |
82 | jnb short get_char |
83 | stosb ; Save it |
84 | call writechr ; Echo to screen |
85 | jmp short get_char |
86 | not_ascii: mov byte [FuncFlag],0 |
87 | cmp al,0Dh ; Enter |
88 | je command_done |
89 | cmp al,'F' & 1Fh ; <Ctrl-F> |
90 | je set_func_flag |
91 | cmp al,'U' & 1Fh ; <Ctrl-U> |
92 | je kill_command ; Kill input line |
93 | cmp al,'V' & 1Fh ; <Ctrl-V> |
94 | je print_version |
95 | cmp al,'X' & 1Fh ; <Ctrl-X> |
96 | je force_text_mode |
97 | cmp al,08h ; Backspace |
98 | jne get_char |
99 | backspace: cmp di,command_line ; Make sure there is anything |
100 | je get_char ; to erase |
101 | dec di ; Unstore one character |
102 | mov si,wipe_char ; and erase it from the screen |
103 | call cwritestr |
104 | jmp short get_char_2 |
105 | |
106 | kill_command: |
107 | call crlf |
108 | jmp enter_command |
109 | |
110 | force_text_mode: |
111 | call vgaclearmode |
112 | jmp enter_command |
113 | |
114 | set_func_flag: |
115 | mov byte [FuncFlag],1 |
116 | get_char_2: |
117 | jmp short get_char |
118 | |
119 | ctrl_f_0: add al,10 ; <Ctrl-F>0 == F10 |
120 | ctrl_f: sub al,'1' |
121 | xor ah,ah |
122 | jmp short show_help |
123 | |
124 | func_key: |
125 | ; AL = 0 if we get here |
126 | xchg al,ah |
127 | cmp al,68 ; F10 |
128 | ja short get_char_2 |
129 | sub al,59 ; F1 |
130 | jb short get_char_2 |
131 | show_help: ; AX = func key # (0 = F1, 9 = F10) |
132 | push di ; Save end-of-cmdline pointer |
133 | shl ax,FILENAME_MAX_LG2 ; Convert to pointer |
134 | add ax,FKeyName |
135 | xchg di,ax |
136 | cmp byte [di+NULLOFFSET],NULLFILE |
137 | je short fk_nofile ; Undefined F-key |
138 | call searchdir |
139 | jz short fk_nofile ; File not found |
140 | push si |
141 | call crlf |
142 | pop si |
143 | call get_msg_file |
144 | jmp short fk_wrcmd |
145 | |
146 | print_version: |
147 | push di ; Command line write pointer |
148 | mov si,syslinux_banner |
149 | call cwritestr |
150 | %ifdef HAVE_BIOSNAME |
151 | mov si,[BIOSName] |
152 | call cwritestr |
153 | %endif |
154 | mov si,copyright_str |
155 | call cwritestr |
156 | |
157 | ; ... fall through ... |
158 | |
159 | ; Write the boot prompt and command line again and |
160 | ; wait for input. Note that this expects the cursor |
161 | ; to already have been CRLF'd, and that the old value |
162 | ; of DI (the command line write pointer) is on the stack. |
163 | fk_wrcmd: |
164 | mov si,boot_prompt |
165 | call cwritestr |
166 | pop di ; Command line write pointer |
167 | push di |
168 | mov byte [di],0 ; Null-terminate command line |
169 | mov si,command_line |
170 | call cwritestr ; Write command line so far |
171 | fk_nofile: pop di |
172 | jmp short get_char_2 |
173 | |
174 | ; |
175 | ; Jump here to run the default command line |
176 | ; |
177 | auto_boot: |
178 | mov si,default_cmd |
179 | mov di,command_line |
180 | mov cx,(max_cmd_len+4) >> 2 |
181 | rep movsd |
182 | jmp short load_kernel |
183 | |
184 | ; |
185 | ; Jump here when the command line is completed |
186 | ; |
187 | command_done: |
188 | call crlf |
189 | cmp di,command_line ; Did we just hit return? |
190 | je auto_boot |
191 | xor al,al ; Store a final null |
192 | stosb |
193 | |
194 | load_kernel: ; Load the kernel now |
195 | ; |
196 | ; First we need to mangle the kernel name the way DOS would... |
197 | ; |
198 | mov si,command_line |
199 | mov di,KernelName |
200 | push si |
201 | push di |
202 | call mangle_name |
203 | pop di |
204 | pop si |
205 | ; |
206 | ; Fast-forward to first option (we start over from the beginning, since |
207 | ; mangle_name doesn't necessarily return a consistent ending state.) |
208 | ; |
209 | clin_non_wsp: lodsb |
210 | cmp al,' ' |
211 | ja clin_non_wsp |
212 | clin_is_wsp: and al,al |
213 | jz clin_opt_ptr |
214 | lodsb |
215 | cmp al,' ' |
216 | jbe clin_is_wsp |
217 | clin_opt_ptr: dec si ; Point to first nonblank |
218 | mov [CmdOptPtr],si ; Save ptr to first option |
219 | ; |
220 | ; If "allowoptions 0", put a null character here in order to ignore any |
221 | ; user-specified options. |
222 | ; |
223 | mov ax,[AllowOptions] |
224 | and ax,ax |
225 | jnz clin_opt_ok |
226 | mov [si],al |
227 | clin_opt_ok: |
228 | |
229 | ; |
230 | ; Now check if it is a "virtual kernel" |
231 | ; |
232 | vk_check: |
233 | xor si,si ; Beginning of vk_seg |
234 | .scan: |
235 | cmp si,[VKernelBytes] |
236 | jae .not_vk |
237 | |
238 | push ds |
239 | push word vk_seg |
240 | pop ds |
241 | |
242 | mov di,VKernelBuf |
243 | call rllunpack |
244 | pop ds |
245 | ; SI updated on return |
246 | |
247 | sub di,cx ; Return to beginning of buf |
248 | push si |
249 | mov si,KernelName |
250 | mov cx,FILENAME_MAX |
251 | es repe cmpsb |
252 | pop si |
253 | je .found |
254 | jmp .scan |
255 | |
256 | ; |
257 | ; We *are* using a "virtual kernel" |
258 | ; |
259 | .found: |
260 | push es |
261 | push word real_mode_seg |
262 | pop es |
263 | mov di,cmd_line_here |
264 | mov si,VKernelBuf+vk_append |
265 | mov cx,[VKernelBuf+vk_appendlen] |
266 | rep movsb |
267 | mov [CmdLinePtr],di ; Where to add rest of cmd |
268 | pop es |
269 | mov di,KernelName |
270 | push di |
271 | mov si,VKernelBuf+vk_rname |
272 | mov cx,FILENAME_MAX ; We need ECX == CX later |
273 | rep movsb |
274 | pop di |
275 | %if IS_PXELINUX |
276 | mov al,[VKernelBuf+vk_ipappend] |
277 | mov [IPAppend],al |
278 | %endif |
279 | xor bx,bx ; Try only one version |
280 | |
281 | %if IS_PXELINUX || IS_ISOLINUX |
282 | ; Is this a "localboot" pseudo-kernel? |
283 | %if IS_PXELINUX |
284 | cmp byte [VKernelBuf+vk_rname+4], 0 |
285 | %else |
286 | cmp byte [VKernelBuf+vk_rname], 0 |
287 | %endif |
288 | jne get_kernel ; No, it's real, go get it |
289 | |
290 | mov ax, [VKernelBuf+vk_rname+1] |
291 | jmp local_boot |
292 | %else |
293 | jmp get_kernel |
294 | %endif |
295 | |
296 | .not_vk: |
297 | |
298 | ; |
299 | ; Not a "virtual kernel" - check that's OK and construct the command line |
300 | ; |
301 | cmp word [AllowImplicit],byte 0 |
302 | je bad_implicit |
303 | push es |
304 | push si |
305 | push di |
306 | mov di,real_mode_seg |
307 | mov es,di |
308 | mov si,AppendBuf |
309 | mov di,cmd_line_here |
310 | mov cx,[AppendLen] |
311 | rep movsb |
312 | mov [CmdLinePtr],di |
313 | pop di |
314 | pop si |
315 | pop es |
316 | ; |
317 | ; Find the kernel on disk |
318 | ; |
319 | get_kernel: mov byte [KernelName+FILENAME_MAX],0 ; Zero-terminate filename/extension |
320 | %if IS_SYSLINUX || IS_MDSLINUX ; SYSLINUX has to deal with DOS mangled names... |
321 | mov eax,[KernelName+8] ; Save initial extension |
322 | mov [exten_table_end],eax ; Last case == initial ext. |
323 | %else |
324 | mov di,KernelName+4*IS_PXELINUX |
325 | xor al,al |
326 | mov cx,FILENAME_MAX-5 ; Need 4 chars + null |
327 | repne scasb ; Scan for final null |
328 | jne .no_skip |
329 | dec di ; Point to final null |
330 | .no_skip: mov [KernelExtPtr],di |
331 | %endif |
332 | mov bx,exten_table |
333 | .search_loop: push bx |
334 | mov di,KernelName ; Search on disk |
335 | call searchdir |
336 | pop bx |
337 | jnz kernel_good |
338 | mov eax,[bx] ; Try a different extension |
339 | %if IS_SYSLINUX || IS_MDSLINUX |
340 | mov [KernelName+8],eax |
341 | %else |
342 | mov si,[KernelExtPtr] |
343 | mov [si],eax |
344 | mov byte [si+4],0 |
345 | %endif |
346 | add bx,byte 4 |
347 | cmp bx,exten_table_end |
348 | jna .search_loop ; allow == case (final case) |
349 | ; Fall into bad_kernel |
350 | ; |
351 | ; bad_kernel: Kernel image not found |
352 | ; bad_implicit: The user entered a nonvirtual kernel name, with "implicit 0" |
353 | ; |
354 | bad_implicit: |
355 | bad_kernel: |
356 | mov cx,[OnerrorLen] |
357 | and cx,cx |
358 | jnz on_error |
359 | .really: |
360 | mov si,KernelName |
361 | mov di,KernelCName |
362 | push di |
363 | call unmangle_name ; Get human form |
364 | mov si,err_notfound ; Complain about missing kernel |
365 | call cwritestr |
366 | pop si ; KernelCName |
367 | call cwritestr |
368 | mov si,crlf_msg |
369 | jmp abort_load ; Ask user for clue |
370 | |
371 | ; |
372 | ; on_error: bad kernel, but we have onerror set |
373 | ; |
374 | on_error: |
375 | mov si,Onerror |
376 | mov di,command_line |
377 | push si ; <A> |
378 | push di ; <B> |
379 | push cx ; <C> |
380 | push cx ; <D> |
381 | push di ; <E> |
382 | repe cmpsb |
383 | pop di ; <E> di == command_line |
384 | pop bx ; <D> bx == [OnerrorLen] |
385 | je bad_kernel.really ; Onerror matches command_line already |
386 | neg bx ; bx == -[OnerrorLen] |
387 | lea cx,[max_cmd_len+bx] |
388 | ; CX == max_cmd_len-[OnerrorLen] |
389 | mov di,command_line+max_cmd_len-1 |
390 | mov byte [di+1],0 ; Enforce null-termination |
391 | lea si,[di+bx] |
392 | std |
393 | rep movsb ; Make space in command_line |
394 | cld |
395 | pop cx ; <C> cx == [OnerrorLen] |
396 | pop di ; <B> di == command_line |
397 | pop si ; <A> si == Onerror |
398 | rep movsb |
399 | jmp load_kernel |
400 | |
401 | ; |
402 | ; kernel_corrupt: Called if the kernel file does not seem healthy |
403 | ; |
404 | kernel_corrupt: mov si,err_notkernel |
405 | jmp abort_load |
406 | |
407 | ; |
408 | ; Get a key, observing ThisKbdTO and ThisTotalTO -- those are timeouts |
409 | ; which can be adjusted by the caller based on the corresponding |
410 | ; master variables; on return they're updated. |
411 | ; |
412 | ; This cheats. If we say "no timeout" we actually get a timeout of |
413 | ; 7.5 years. |
414 | ; |
415 | getchar_timeout: |
416 | call vgashowcursor |
417 | RESET_IDLE |
418 | |
419 | .loop: |
420 | push word [BIOS_timer] |
421 | call pollchar |
422 | jnz .got_char |
423 | pop ax |
424 | cmp ax,[BIOS_timer] ; Has the timer advanced? |
425 | je .loop |
426 | DO_IDLE |
427 | |
428 | dec dword [ThisKbdTo] |
429 | jz .timeout |
430 | dec dword [ThisTotalTo] |
431 | jnz .loop |
432 | |
433 | .timeout: |
434 | ; Timeout!!!! |
435 | pop cx ; Discard return address |
436 | call vgahidecursor |
437 | mov si,Ontimeout ; Copy ontimeout command |
438 | mov di,command_line |
439 | mov cx,[OntimeoutLen] ; if we have one... |
440 | rep movsb |
441 | jmp command_done |
442 | |
443 | .got_char: |
444 | pop cx ; Discard |
445 | call getchar |
446 | call vgahidecursor |
447 | ret |
448 | |
449 | ; |
450 | ; This is it! We have a name (and location on the disk)... let's load |
451 | ; that sucker!! First we have to decide what kind of file this is; base |
452 | ; that decision on the file extension. The following extensions are |
453 | ; recognized; case insensitive: |
454 | ; |
455 | ; .com - COMBOOT image |
456 | ; .cbt - COMBOOT image |
457 | ; .c32 - COM32 image |
458 | ; .bs - Boot sector |
459 | ; .0 - PXE bootstrap program (PXELINUX only) |
460 | ; .bin - Boot sector |
461 | ; .bss - Boot sector, but transfer over DOS superblock (SYSLINUX only) |
462 | ; .img - Floppy image (ISOLINUX only) |
463 | ; |
464 | ; Anything else is assumed to be a Linux kernel. |
465 | ; |
466 | section .bss |
467 | alignb 4 |
468 | Kernel_EAX resd 1 |
469 | Kernel_SI resw 1 |
470 | |
471 | section .text |
472 | kernel_good_saved: |
473 | ; Alternate entry point for which the return from |
474 | ; searchdir is stored in memory. This is used for |
475 | ; COMBOOT function INT 22h, AX=0016h. |
476 | mov si,[Kernel_SI] |
477 | mov eax,[Kernel_EAX] |
478 | mov dx,[Kernel_EAX+2] |
479 | |
480 | kernel_good: |
481 | pusha |
482 | mov si,KernelName |
483 | mov di,KernelCName |
484 | call unmangle_name |
485 | sub di,KernelCName |
486 | mov [KernelCNameLen],di |
487 | popa |
488 | |
489 | %if IS_SYSLINUX || IS_MDSLINUX |
490 | mov ecx,[KernelName+7] |
491 | mov cl,'.' |
492 | %else |
493 | push di |
494 | push ax |
495 | mov di,KernelName+4*IS_PXELINUX |
496 | xor al,al |
497 | mov cx,FILENAME_MAX |
498 | repne scasb |
499 | jne .one_step |
500 | dec di |
501 | .one_step: mov ecx,[di-4] ; 4 bytes before end |
502 | pop ax |
503 | pop di |
504 | %endif |
505 | |
506 | ; |
507 | ; At this point, DX:AX contains the size of the kernel, and SI contains |
508 | ; the file handle/cluster pointer. |
509 | ; |
510 | or ecx,20202000h ; Force lower case |
511 | |
512 | cmp ecx,'.com' |
513 | je is_comboot_image |
514 | cmp ecx,'.cbt' |
515 | je is_comboot_image |
516 | cmp ecx,'.c32' |
517 | je is_com32_image |
518 | %if IS_ISOLINUX |
519 | cmp ecx,'.img' |
520 | je is_disk_image |
521 | %endif |
522 | cmp ecx,'.bss' |
523 | je is_bss_sector |
524 | cmp ecx,'.bin' |
525 | je is_bootsector |
526 | %if IS_SYSLINUX || IS_MDSLINUX |
527 | cmp ecx,'.bs ' |
528 | je is_bootsector |
529 | cmp ecx,'.0 ' |
530 | je is_bootsector |
531 | %else |
532 | shr ecx,8 |
533 | cmp ecx,'.bs' |
534 | je is_bootsector |
535 | shr ecx,8 |
536 | cmp cx,'.0' |
537 | je is_bootsector |
538 | %endif |
539 | ; Otherwise Linux kernel |
540 | |
541 | section .bss |
542 | alignb 4 |
543 | ThisKbdTo resd 1 ; Temporary holder for KbdTimeout |
544 | ThisTotalTo resd 1 ; Temporary holder for TotalTimeout |
545 | KernelExtPtr resw 1 ; During search, final null pointer |
546 | CmdOptPtr resw 1 ; Pointer to first option on cmd line |
547 | KbdFlags resb 1 ; Check for keyboard escapes |
548 | FuncFlag resb 1 ; Escape sequences received from keyboard |
549 | |
550 | section .text |