Chinaunix首页 | 论坛 | 博客

net

  • 博客访问: 136929
  • 博文数量: 4
  • 博客积分: 1995
  • 博客等级: 上尉
  • 技术积分: 320
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-06 15:30
文章分类

全部博文(4)

文章存档

2008年(4)

我的朋友
最近访客

分类: LINUX

2008-04-29 09:05:06

  1 /*
  2  *  GRUB  --  GRand Unified Bootloader
  3  *  Copyright (C) 1999,2000,2001   Free Software Foundation, Inc.
  4  *
  5  *  This program is free software; you can redistribute it and/or modify
  6  *  it under the terms of the GNU General Public License as published by
  7  *  the Free Software Foundation; either version 2 of the License, or
  8  *  (at your option) any later version.
  9  *
 10  *  This program is distributed in the hope that it will be useful,
 11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13  *  GNU General Public License for more details.
 14  *
 15  *  You should have received a copy of the GNU General Public License
 16  *  along with this program; if not, write to the Free Software
 17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 18  */
 19
 20 #define ASM_FILE
 21 #include <shared.h>
 22
 23 #ifndef STAGE1_5
 24 #include <stage2_size.h>
 25 #endif
 26         
 27 /*
 28  *  defines for the code go here
 29  */
 30
 31         /* Absolute addresses
 32            This makes the assembler generate the address without support
 33            from the linker. (ELF can't relocate 16-bit addresses!) */
 34 #ifdef STAGE1_5
 35 # define ABS(x) (x-_start+0x2000)
 36 #else
 37 # define ABS(x) (x-_start+0x8000)
 38 #endif /* STAGE1_5 */
 39         
 40         /* Print message string */
 41 #define MSG(x)  movw $ABS(x), %si; call message
 42
 43         .file  "start.S"
 44
 45         .text
 46
 47         /* Tell GAS to generate 16-bit instructions so that this code works
 48            in real mode. */
 49         .code16
 50
 51         .globl start, _start
 52 start:
 53 _start:
 54         /*
 55          * _start is loaded at 0x8000 and is jumped to with
 56          * CS:IP 0:0x8000 in stage2.
 57          */
 58
 59         /*
 60          * we continue to use the stack for stage1 and assume that
 61          * some registers are set to correct values. See stage1.S
 62          * for more information.
 63          */
 64         
 65         /* save drive reference first thing! */
 66         pushw  %dx
 67
 68         /* print a notification message on the screen */
 69         pushw  %si
 70         MSG(notification_string)
 71         popw   %si
 72         
 73         /* this sets up for the first run through "bootloop" */
 74         movw   $ABS(firstlist - BOOTSEC_LISTSIZE), %di
 75
 76         /* save the sector number of the second sector in %ebp */
 77         movl   (%di), %ebp
 78
 79         /* this is the loop for reading the secondary boot-loader in */
 80 bootloop:
 81
 82         /* check the number of sectors to read */
 83         cmpw   $0, 4(%di)
 84
 85         /* if zero, go to the start function */
 86         je     bootit
 87
 88 setup_sectors:  
 89         /* check if we use LBA or CHS */
 90         cmpb   $0, -1(%si)
 91
 92         /* jump to chs_mode if zero */
 93         je     chs_mode
 94
 95 lba_mode:      
 96         /* load logical sector start */
 97         movl   (%di), %ebx
 98
 99         /* the maximum is limited to 0x7f because of Phoenix EDD */
100         xorl   %eax, %eax
101         movb   $0x7f, %al
102
103         /* how many do we really want to read? */
104         cmpw   %ax, 4(%di)       /* compare against total number of sectors */
105
106         /* which is greater? */
107         jg     1f
108
109         /* if less than, set to total */
110         movw   4(%di), %ax
111
112 1:      
113         /* subtract from total */
114         subw   %ax, 4(%di)
115
116         /* add into logical sector start */
117         addl   %eax, (%di)
118
119         /* set up disk address packet */
120
121         /* the size and the reserved byte */
122         movw   $0x0010, (%si)
123
124         /* the number of sectors */
125         movw   %ax, 2(%si)
126
127         /* the absolute address (low 32 bits) */
128         movl   %ebx, 8(%si)
129
130         /* the segment of buffer address */
131         movw   $BUFFERSEG, 6(%si)
132
133         /* save %ax from destruction! */
134         pushw  %ax
135
136         /* zero %eax */
137         xorl   %eax, %eax
138
139         /* the offset of buffer address */
140         movw   %ax, 4(%si)
141
142         /* the absolute address (high 32 bits) */
143         movl   %eax, 12(%si)
144
145
146 /*
147  * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory
148  *      Call with    %ah = 0x42
149  *                      %dl = drive number
150  *                      %ds:%si = segment:offset of disk address packet
151  *      Return:
152  *                      %al = 0x0 on success; err code on failure
153  */
154
155         movb   $0x42, %ah
156         int    $0x13
157
158         jc     read_error
159
160         movw   $BUFFERSEG, %bx
161         jmp    copy_buffer
162                         
163 chs_mode:      
164         /* load logical sector start (bottom half) */
165         movl   (%di), %eax
166
167         /* zero %edx */
168         xorl   %edx, %edx
169
170         /* divide by number of sectors */
171         divl   (%si)
172
173         /* save sector start */
174         movb   %dl, 10(%si)
175
176         xorl   %edx, %edx        /* zero %edx */
177         divl   4(%si)            /* divide by number of heads */
178
179         /* save head start */
180         movb   %dl, 11(%si)
181
182         /* save cylinder start */
183         movw   %ax, 12(%si)
184
185         /* do we need too many cylinders? */
186         cmpw   8(%si), %ax
187         jge    geometry_error
188
189         /* determine the maximum sector length of this read */
190         movw   (%si), %ax        /* get number of sectors per track/head */
191
192         /* subtract sector start */
193         subb   10(%si), %al
194
195         /* how many do we really want to read? */
196         cmpw   %ax, 4(%di)       /* compare against total number of sectors */
197
198
199         /* which is greater? */
200         jg     2f
201
202         /* if less than, set to total */
203         movw   4(%di), %ax
204
205 2:      
206         /* subtract from total */
207         subw   %ax, 4(%di)
208
209         /* add into logical sector start */
210         addl   %eax, (%di)
211
212 /*
213  *  This is the loop for taking care of BIOS geometry translation (ugh!)
214  */
215
216         /* get high bits of cylinder */
217         movb   13(%si), %dl
218
219         shlb   $6, %dl           /* shift left by 6 bits */
220         movb   10(%si), %cl      /* get sector */
221
222         incb   %cl               /* normalize sector (sectors go
223                                         from 1-N, not 0-(N-1) ) */
224         orb    %dl, %cl   /* composite together */
225         movb   12(%si), %ch      /* sector+hcyl in cl, cylinder in ch */
226
227         /* restore %dx */
228         popw   %dx
229         pushw  %dx
230
231         /* head number */
232         movb   11(%si), %dh
233
234         pushw  %ax      /* save %ax from destruction! */
235
236 /*
237  * BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
238  *      Call with    %ah = 0x2
239  *                      %al = number of sectors
240  *                      %ch = cylinder
241  *                      %cl = sector (bits 6-7 are high bits of "cylinder")
242  *                      %dh = head
243  *                      %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
244  *                      %es:%bx = segment:offset of buffer
245  *      Return:
246  *                      %al = 0x0 on success; err code on failure
247  */
248
249         movw   $BUFFERSEG, %bx
250         movw   %bx, %es  /* load %es segment with disk buffer */
251
252         xorw   %bx, %bx  /* %bx = 0, put it at 0 in the segment */
253         movb   $0x2, %ah /* function 2 */
254         int    $0x13
255
256         jc     read_error
257
258         /* save source segment */
259         movw   %es, %bx
260         
261 copy_buffer:    
262
263         /* load addresses for copy from disk buffer to destination */
264         movw   6(%di), %es       /* load destination segment */
265
266         /* restore %ax */
267         popw   %ax
268
269         /* determine the next possible destination address (presuming
270                 512 byte sectors!) */
271         shlw   $5, %ax           /* shift %ax five bits to the left */
272         addw   %ax, 6(%di)       /* add the corrected value to the destination
273                                    address for next time */
274
275         /* save addressing regs */
276         pusha
277         pushw  %ds
278
279         /* get the copy length */
280         shlw   $4, %ax
281         movw   %ax, %cx
282
283         xorw   %di, %di  /* zero offset of destination addresses */
284         xorw   %si, %si  /* zero offset of source addresses */
285         movw   %bx, %ds  /* restore the source segment */
286
287         cld            /* sets the copy direction to forward */
288
289         /* perform copy */
290         rep            /* sets a repeat */
291         movsb          /* this runs the actual copy */
292
293         /* restore addressing regs and print a dot with correct DS 
294            (MSG modifies SI, which is saved, and unused AX and BX) */
295         popw   %ds
296         MSG(notification_step)
297         popa
298
299         /* check if finished with this dataset */
300         cmpw   $0, 4(%di)
301         jne    setup_sectors
302
303         /* update position to load from */
304         subw   $BOOTSEC_LISTSIZE, %di
305
306         /* jump to bootloop */
307         jmp    bootloop
308
309 /* END OF MAIN LOOP */
310
311 bootit:
312         /* print a newline */
313         MSG(notification_done)
314         popw   %dx       /* this makes sure %dl is our "boot" drive */
315 #ifdef STAGE1_5
316         ljmp   $0, $0x2200
317 #else /* ! STAGE1_5 */
318         ljmp   $0, $0x8200
319 #endif /* ! STAGE1_5 */
320
321
322 /*
323  * BIOS Geometry translation error (past the end of the disk geometry!).
324  */
325 geometry_error:
326         MSG(geometry_error_string)
327         jmp    general_error
328
329 /*
330  * Read error on the disk.
331  */
332 read_error:
333         MSG(read_error_string)
334
335 general_error:
336         MSG(general_error_string)
337
338 /* go here when you need to stop the machine hard after an error condition */
339 stop:   jmp       stop
340
341 #ifdef STAGE1_5
342 notification_string:    .string "Loading stage1.5"
343 #else
344 notification_string:    .string "Loading stage2"
345 #endif
346
347 notification_step:      .string "."
348 notification_done:      .string "\r\n"
349         
350 geometry_error_string:  .string "Geom"
351 read_error_string:      .string "Read"
352 general_error_string:   .string " Error"
353
354 /*
355  * message: write the string pointed to by %si
356  *
357  *   WARNING: trashes %si, %ax, and %bx
358  */
359
360         /*
361          * Use BIOS "int 10H Function 0Eh" to write character in teletype mode
362          *      %ah = 0xe   %al = character
363          *      %bh = page  %bl = foreground color (graphics modes)
364          */
365 1:
366         movw   $0x0001, %bx
367         movb   $0xe, %ah
368         int    $0x10              /* display a byte */
369
370         incw   %si
371 message:
372         movb   (%si), %al
373         cmpb   $0, %al
374         jne    1b /* if not end of string, jmp to display */
375         ret
376 lastlist:
377
378 /*
379  *  This area is an empty space between the main body of code below which
380  *  grows up (fixed after compilation, but between releases it may change
381  *  in size easily), and the lists of sectors to read, which grows down
382  *  from a fixed top location.
383  */
384
385         .word 0
386         .word 0
387
388         . = _start + 0x200 - BOOTSEC_LISTSIZE
389         
390         /* fill the first data listing with the default */
391 blocklist_default_start:
392         .long 2                /* this is the sector start parameter, in logical
393                            sectors from the start of the disk, sector 0 */
394 blocklist_default_len:
395                         /* this is the number of sectors to read */
396 #ifdef STAGE1_5
397         .word 0               /* the command "install" will fill this up */
398 #else
399         .word (STAGE2_SIZE + 511) >> 9
400 #endif
401 blocklist_default_seg:
402 #ifdef STAGE1_5
403         .word 0x220
404 #else
405         .word 0x820    /* this is the segment of the starting address
406                            to load the data into */
407 #endif
408         
409 firstlist:      /* this label has to be after the list data!!! */
阅读(2326) | 评论(0) | 转发(0) |
0

上一篇:grub grub\stage1\stage1.s

下一篇:没有了

给主人留下些什么吧!~~