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>
33 #include <grub/cpu/tsc.h>
41 #define MAX_REGIONS 32
43 static struct mem_region mem_regions
[MAX_REGIONS
];
44 static int num_regions
;
46 grub_addr_t grub_os_area_addr
;
47 grub_size_t grub_os_area_size
;
48 grub_size_t grub_lower_mem
, grub_upper_mem
;
51 grub_arch_sync_caches (void *address
__attribute__ ((unused
)),
52 grub_size_t len
__attribute__ ((unused
)))
57 make_install_device (void)
59 /* XXX: This should be enough. */
62 if (grub_prefix
[0] != '(')
64 /* If the root drive is not set explicitly, assume that it is identical
66 if (grub_root_drive
== 0xFF)
67 grub_root_drive
= grub_boot_drive
;
69 grub_sprintf (dev
, "(%cd%u", (grub_root_drive
& 0x80) ? 'h' : 'f',
70 grub_root_drive
& 0x7f);
72 if (grub_install_dos_part
>= 0)
73 grub_sprintf (dev
+ grub_strlen (dev
), ",%u", grub_install_dos_part
+ 1);
75 if (grub_install_bsd_part
>= 0)
76 grub_sprintf (dev
+ grub_strlen (dev
), ",%c", grub_install_bsd_part
+ 'a');
78 grub_sprintf (dev
+ grub_strlen (dev
), ")%s", grub_prefix
);
79 grub_strcpy (grub_prefix
, dev
);
85 /* Add a memory region. */
87 add_mem_region (grub_addr_t addr
, grub_size_t size
)
89 if (num_regions
== MAX_REGIONS
)
93 mem_regions
[num_regions
].addr
= addr
;
94 mem_regions
[num_regions
].size
= size
;
98 /* Compact memory regions. */
100 compact_mem_regions (void)
105 for (i
= 0; i
< num_regions
- 1; i
++)
106 for (j
= i
+ 1; j
< num_regions
; j
++)
107 if (mem_regions
[i
].addr
> mem_regions
[j
].addr
)
109 struct mem_region tmp
= mem_regions
[i
];
110 mem_regions
[i
] = mem_regions
[j
];
111 mem_regions
[j
] = tmp
;
114 /* Merge overlaps. */
115 for (i
= 0; i
< num_regions
- 1; i
++)
116 if (mem_regions
[i
].addr
+ mem_regions
[i
].size
>= mem_regions
[i
+ 1].addr
)
120 if (mem_regions
[i
].addr
+ mem_regions
[i
].size
121 < mem_regions
[j
].addr
+ mem_regions
[j
].size
)
122 mem_regions
[i
].size
= (mem_regions
[j
].addr
+ mem_regions
[j
].size
123 - mem_regions
[i
].addr
);
125 grub_memmove (mem_regions
+ j
, mem_regions
+ j
+ 1,
126 (num_regions
- j
- 1) * sizeof (struct mem_region
));
133 grub_machine_init (void)
137 /* Initialize the console as early as possible. */
138 grub_console_init ();
140 grub_lower_mem
= grub_get_memsize (0) << 10;
143 if (grub_lower_mem
< GRUB_MEMORY_MACHINE_RESERVED_END
)
144 grub_fatal ("too small memory");
147 /* Turn on Gate A20 to access >1MB. */
151 /* Add the lower memory into free memory. */
152 if (grub_lower_mem
>= GRUB_MEMORY_MACHINE_RESERVED_END
)
153 add_mem_region (GRUB_MEMORY_MACHINE_RESERVED_END
,
154 grub_lower_mem
- GRUB_MEMORY_MACHINE_RESERVED_END
);
156 auto int NESTED_FUNC_ATTR
hook (grub_uint64_t
, grub_uint64_t
, grub_uint32_t
);
157 int NESTED_FUNC_ATTR
hook (grub_uint64_t addr
, grub_uint64_t size
, grub_uint32_t type
)
159 /* Avoid the lower memory. */
162 if (size
<= 0x100000 - addr
)
165 size
-= 0x100000 - addr
;
170 if (addr
<= 0xFFFFFFFF && type
== GRUB_MACHINE_MEMORY_AVAILABLE
)
174 len
= (grub_size_t
) ((addr
+ size
> 0xFFFFFFFF)
177 add_mem_region (addr
, len
);
183 grub_machine_mmap_iterate (hook
);
185 compact_mem_regions ();
187 /* Add the memory regions to free memory, except for the region starting
188 from 1MB. This region is partially used for loading OS images.
189 For now, 1/4 of this is added to free memory. */
190 for (i
= 0; i
< num_regions
; i
++)
191 if (mem_regions
[i
].addr
== 0x100000)
193 grub_size_t quarter
= mem_regions
[i
].size
>> 2;
195 grub_upper_mem
= mem_regions
[i
].size
;
196 grub_os_area_addr
= mem_regions
[i
].addr
;
197 grub_os_area_size
= mem_regions
[i
].size
- quarter
;
198 grub_mm_init_region ((void *) (grub_os_area_addr
+ grub_os_area_size
),
202 grub_mm_init_region ((void *) mem_regions
[i
].addr
, mem_regions
[i
].size
);
204 if (! grub_os_area_addr
)
205 grub_fatal ("no upper memory");
211 grub_machine_set_prefix (void)
213 /* Initialize the prefix. */
214 grub_env_set ("prefix", make_install_device ());
218 grub_machine_fini (void)
220 grub_console_fini ();
223 /* Return the end of the core image. */
225 grub_arch_modules_addr (void)
227 return GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR
228 + (grub_kernel_image_size
- GRUB_KERNEL_MACHINE_RAW_SIZE
);