Annotation of /tags/mkinitrd-6_1_2/isolinux/ui.inc
Parent Directory | Revision Log
Revision 844 -
(hide annotations)
(download)
Mon May 4 17:23:09 2009 UTC (15 years, 4 months ago) by niro
File size: 13067 byte(s)
Mon May 4 17:23:09 2009 UTC (15 years, 4 months ago) by niro
File size: 13067 byte(s)
tagged 'mkinitrd-6_1_2'
1 | niro | 532 | ;; $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 |