2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc.
5 * GRUB 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 3 of the License, or
8 * (at your option) any later version.
10 * GRUB 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.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include <grub/kernel.h>
21 #include <grub/machine/init.h>
22 #include <grub/machine/memory.h>
23 #include <grub/machine/console.h>
24 #include <grub/machine/kernel.h>
25 #include <grub/types.h>
28 #include <grub/misc.h>
29 #include <grub/loader.h>
31 #include <grub/cache.h>
32 #include <grub/time.h>
40 #define MAX_REGIONS 32
42 static struct mem_region mem_regions
[MAX_REGIONS
];
43 static int num_regions
;
45 grub_addr_t grub_os_area_addr
;
46 grub_size_t grub_os_area_size
;
47 grub_size_t grub_lower_mem
, grub_upper_mem
;
50 grub_millisleep (grub_uint32_t ms
)
52 grub_millisleep_generic (ms
);
56 grub_arch_sync_caches (void *address
__attribute__ ((unused
)),
57 grub_size_t len
__attribute__ ((unused
)))
62 make_install_device (void)
64 /* XXX: This should be enough. */
67 if (grub_memdisk_image_size
)
69 grub_sprintf (dev
, "(memdisk)%s", grub_prefix
);
70 grub_strcpy (grub_prefix
, dev
);
72 else if (grub_install_dos_part
!= -2)
74 /* If the root drive is not set explicitly, assume that it is identical
76 if (grub_root_drive
== 0xFF)
77 grub_root_drive
= grub_boot_drive
;
79 grub_sprintf (dev
, "(%cd%u", (grub_root_drive
& 0x80) ? 'h' : 'f',
80 grub_root_drive
& 0x7f);
82 if (grub_install_dos_part
>= 0)
83 grub_sprintf (dev
+ grub_strlen (dev
), ",%u", grub_install_dos_part
+ 1);
85 if (grub_install_bsd_part
>= 0)
86 grub_sprintf (dev
+ grub_strlen (dev
), ",%c", grub_install_bsd_part
+ 'a');
88 grub_sprintf (dev
+ grub_strlen (dev
), ")%s", grub_prefix
);
89 grub_strcpy (grub_prefix
, dev
);
95 /* Add a memory region. */
97 add_mem_region (grub_addr_t addr
, grub_size_t size
)
99 if (num_regions
== MAX_REGIONS
)
103 mem_regions
[num_regions
].addr
= addr
;
104 mem_regions
[num_regions
].size
= size
;
108 /* Compact memory regions. */
110 compact_mem_regions (void)
115 for (i
= 0; i
< num_regions
- 1; i
++)
116 for (j
= i
+ 1; j
< num_regions
; j
++)
117 if (mem_regions
[i
].addr
> mem_regions
[j
].addr
)
119 struct mem_region tmp
= mem_regions
[i
];
120 mem_regions
[i
] = mem_regions
[j
];
121 mem_regions
[j
] = tmp
;
124 /* Merge overlaps. */
125 for (i
= 0; i
< num_regions
- 1; i
++)
126 if (mem_regions
[i
].addr
+ mem_regions
[i
].size
>= mem_regions
[i
+ 1].addr
)
130 if (mem_regions
[i
].addr
+ mem_regions
[i
].size
131 < mem_regions
[j
].addr
+ mem_regions
[j
].size
)
132 mem_regions
[i
].size
= (mem_regions
[j
].addr
+ mem_regions
[j
].size
133 - mem_regions
[i
].addr
);
135 grub_memmove (mem_regions
+ j
, mem_regions
+ j
+ 1,
136 (num_regions
- j
- 1) * sizeof (struct mem_region
));
143 grub_machine_init (void)
146 struct grub_machine_mmap_entry
*entry
147 = (struct grub_machine_mmap_entry
*) GRUB_MEMORY_MACHINE_SCRATCH_ADDR
;
150 /* Initialize the console as early as possible. */
151 grub_console_init ();
153 grub_lower_mem
= grub_get_memsize (0) << 10;
156 if (grub_lower_mem
< GRUB_MEMORY_MACHINE_RESERVED_END
)
157 grub_fatal ("too small memory");
160 /* Turn on Gate A20 to access >1MB. */
164 /* Add the lower memory into free memory. */
165 if (grub_lower_mem
>= GRUB_MEMORY_MACHINE_RESERVED_END
)
166 add_mem_region (GRUB_MEMORY_MACHINE_RESERVED_END
,
167 grub_lower_mem
- GRUB_MEMORY_MACHINE_RESERVED_END
);
169 /* Check if grub_get_mmap_entry works. */
170 cont
= grub_get_mmap_entry (entry
, 0);
175 /* Avoid the lower memory. */
176 if (entry
->addr
< 0x100000)
178 if (entry
->len
<= 0x100000 - entry
->addr
)
181 entry
->len
-= 0x100000 - entry
->addr
;
182 entry
->addr
= 0x100000;
186 if (entry
->addr
<= 0xFFFFFFFF && entry
->type
== 1)
191 addr
= (grub_addr_t
) entry
->addr
;
192 len
= ((addr
+ entry
->len
> 0xFFFFFFFF)
194 : (grub_size_t
) entry
->len
);
195 add_mem_region (addr
, len
);
202 cont
= grub_get_mmap_entry (entry
, cont
);
207 grub_uint32_t eisa_mmap
= grub_get_eisa_mmap ();
211 add_mem_region (0x100000, (eisa_mmap
& 0xFFFF) << 10);
212 add_mem_region (0x1000000, eisa_mmap
& ~0xFFFF);
215 add_mem_region (0x100000, grub_get_memsize (1) << 10);
218 compact_mem_regions ();
220 /* Add the memory regions to free memory, except for the region starting
221 from 1MB. This region is partially used for loading OS images.
222 For now, 1/4 of this is added to free memory. */
223 for (i
= 0; i
< num_regions
; i
++)
224 if (mem_regions
[i
].addr
== 0x100000)
226 grub_size_t quarter
= mem_regions
[i
].size
>> 2;
228 grub_upper_mem
= mem_regions
[i
].size
;
229 grub_os_area_addr
= mem_regions
[i
].addr
;
230 grub_os_area_size
= mem_regions
[i
].size
- quarter
;
231 grub_mm_init_region ((void *) (grub_os_area_addr
+ grub_os_area_size
),
235 grub_mm_init_region ((void *) mem_regions
[i
].addr
, mem_regions
[i
].size
);
237 if (! grub_os_area_addr
)
238 grub_fatal ("no upper memory");
242 grub_machine_set_prefix (void)
244 /* Initialize the prefix. */
245 grub_env_set ("prefix", make_install_device ());
249 grub_machine_fini (void)
251 grub_console_fini ();
254 /* Return the end of the core image. */
256 grub_arch_modules_addr (void)
258 return grub_end_addr
;
261 /* Return the start of the memdisk image. */
263 grub_arch_memdisk_addr (void)
265 return GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR
266 + (grub_kernel_image_size
- GRUB_KERNEL_MACHINE_RAW_SIZE
)
267 + grub_total_module_size
;
270 /* Return the size of the memdisk image. */
272 grub_arch_memdisk_size (void)
274 return grub_memdisk_image_size
;