diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-29 00:09:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-29 00:09:26 -0400 |
commit | 8a212ab6b8a4ccc6f3c3d1beba5f92655c576404 (patch) | |
tree | 525271129ff9c692defdd20566f1f7203b18ff24 /arch/ia64/kernel/efi.c | |
parent | 1f419cadff55f548e7356ffebdb9e1b5a8c22275 (diff) | |
parent | 0e1f60609258e18ec0a0477c646101212822d387 (diff) |
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
Diffstat (limited to 'arch/ia64/kernel/efi.c')
-rw-r--r-- | arch/ia64/kernel/efi.c | 510 |
1 files changed, 329 insertions, 181 deletions
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 179f230816ed..f72ea6aebcb1 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c | |||
@@ -239,57 +239,30 @@ is_available_memory (efi_memory_desc_t *md) | |||
239 | return 0; | 239 | return 0; |
240 | } | 240 | } |
241 | 241 | ||
242 | /* | 242 | typedef struct kern_memdesc { |
243 | * Trim descriptor MD so its starts at address START_ADDR. If the descriptor covers | 243 | u64 attribute; |
244 | * memory that is normally available to the kernel, issue a warning that some memory | 244 | u64 start; |
245 | * is being ignored. | 245 | u64 num_pages; |
246 | */ | 246 | } kern_memdesc_t; |
247 | static void | ||
248 | trim_bottom (efi_memory_desc_t *md, u64 start_addr) | ||
249 | { | ||
250 | u64 num_skipped_pages; | ||
251 | 247 | ||
252 | if (md->phys_addr >= start_addr || !md->num_pages) | 248 | static kern_memdesc_t *kern_memmap; |
253 | return; | ||
254 | |||
255 | num_skipped_pages = (start_addr - md->phys_addr) >> EFI_PAGE_SHIFT; | ||
256 | if (num_skipped_pages > md->num_pages) | ||
257 | num_skipped_pages = md->num_pages; | ||
258 | |||
259 | if (is_available_memory(md)) | ||
260 | printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx due to granule hole " | ||
261 | "at 0x%lx\n", __FUNCTION__, | ||
262 | (num_skipped_pages << EFI_PAGE_SHIFT) >> 10, | ||
263 | md->phys_addr, start_addr - IA64_GRANULE_SIZE); | ||
264 | /* | ||
265 | * NOTE: Don't set md->phys_addr to START_ADDR because that could cause the memory | ||
266 | * descriptor list to become unsorted. In such a case, md->num_pages will be | ||
267 | * zero, so the Right Thing will happen. | ||
268 | */ | ||
269 | md->phys_addr += num_skipped_pages << EFI_PAGE_SHIFT; | ||
270 | md->num_pages -= num_skipped_pages; | ||
271 | } | ||
272 | 249 | ||
273 | static void | 250 | static void |
274 | trim_top (efi_memory_desc_t *md, u64 end_addr) | 251 | walk (efi_freemem_callback_t callback, void *arg, u64 attr) |
275 | { | 252 | { |
276 | u64 num_dropped_pages, md_end_addr; | 253 | kern_memdesc_t *k; |
277 | 254 | u64 start, end, voff; | |
278 | md_end_addr = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT); | ||
279 | |||
280 | if (md_end_addr <= end_addr || !md->num_pages) | ||
281 | return; | ||
282 | 255 | ||
283 | num_dropped_pages = (md_end_addr - end_addr) >> EFI_PAGE_SHIFT; | 256 | voff = (attr == EFI_MEMORY_WB) ? PAGE_OFFSET : __IA64_UNCACHED_OFFSET; |
284 | if (num_dropped_pages > md->num_pages) | 257 | for (k = kern_memmap; k->start != ~0UL; k++) { |
285 | num_dropped_pages = md->num_pages; | 258 | if (k->attribute != attr) |
286 | 259 | continue; | |
287 | if (is_available_memory(md)) | 260 | start = PAGE_ALIGN(k->start); |
288 | printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx due to granule hole " | 261 | end = (k->start + (k->num_pages << EFI_PAGE_SHIFT)) & PAGE_MASK; |
289 | "at 0x%lx\n", __FUNCTION__, | 262 | if (start < end) |
290 | (num_dropped_pages << EFI_PAGE_SHIFT) >> 10, | 263 | if ((*callback)(start + voff, end + voff, arg) < 0) |
291 | md->phys_addr, end_addr); | 264 | return; |
292 | md->num_pages -= num_dropped_pages; | 265 | } |
293 | } | 266 | } |
294 | 267 | ||
295 | /* | 268 | /* |
@@ -299,148 +272,19 @@ trim_top (efi_memory_desc_t *md, u64 end_addr) | |||
299 | void | 272 | void |
300 | efi_memmap_walk (efi_freemem_callback_t callback, void *arg) | 273 | efi_memmap_walk (efi_freemem_callback_t callback, void *arg) |
301 | { | 274 | { |
302 | int prev_valid = 0; | 275 | walk(callback, arg, EFI_MEMORY_WB); |
303 | struct range { | ||
304 | u64 start; | ||
305 | u64 end; | ||
306 | } prev, curr; | ||
307 | void *efi_map_start, *efi_map_end, *p, *q; | ||
308 | efi_memory_desc_t *md, *check_md; | ||
309 | u64 efi_desc_size, start, end, granule_addr, last_granule_addr, first_non_wb_addr = 0; | ||
310 | unsigned long total_mem = 0; | ||
311 | |||
312 | efi_map_start = __va(ia64_boot_param->efi_memmap); | ||
313 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | ||
314 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | ||
315 | |||
316 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { | ||
317 | md = p; | ||
318 | |||
319 | /* skip over non-WB memory descriptors; that's all we're interested in... */ | ||
320 | if (!(md->attribute & EFI_MEMORY_WB)) | ||
321 | continue; | ||
322 | |||
323 | /* | ||
324 | * granule_addr is the base of md's first granule. | ||
325 | * [granule_addr - first_non_wb_addr) is guaranteed to | ||
326 | * be contiguous WB memory. | ||
327 | */ | ||
328 | granule_addr = GRANULEROUNDDOWN(md->phys_addr); | ||
329 | first_non_wb_addr = max(first_non_wb_addr, granule_addr); | ||
330 | |||
331 | if (first_non_wb_addr < md->phys_addr) { | ||
332 | trim_bottom(md, granule_addr + IA64_GRANULE_SIZE); | ||
333 | granule_addr = GRANULEROUNDDOWN(md->phys_addr); | ||
334 | first_non_wb_addr = max(first_non_wb_addr, granule_addr); | ||
335 | } | ||
336 | |||
337 | for (q = p; q < efi_map_end; q += efi_desc_size) { | ||
338 | check_md = q; | ||
339 | |||
340 | if ((check_md->attribute & EFI_MEMORY_WB) && | ||
341 | (check_md->phys_addr == first_non_wb_addr)) | ||
342 | first_non_wb_addr += check_md->num_pages << EFI_PAGE_SHIFT; | ||
343 | else | ||
344 | break; /* non-WB or hole */ | ||
345 | } | ||
346 | |||
347 | last_granule_addr = GRANULEROUNDDOWN(first_non_wb_addr); | ||
348 | if (last_granule_addr < md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) | ||
349 | trim_top(md, last_granule_addr); | ||
350 | |||
351 | if (is_available_memory(md)) { | ||
352 | if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) >= max_addr) { | ||
353 | if (md->phys_addr >= max_addr) | ||
354 | continue; | ||
355 | md->num_pages = (max_addr - md->phys_addr) >> EFI_PAGE_SHIFT; | ||
356 | first_non_wb_addr = max_addr; | ||
357 | } | ||
358 | |||
359 | if (total_mem >= mem_limit) | ||
360 | continue; | ||
361 | |||
362 | if (total_mem + (md->num_pages << EFI_PAGE_SHIFT) > mem_limit) { | ||
363 | unsigned long limit_addr = md->phys_addr; | ||
364 | |||
365 | limit_addr += mem_limit - total_mem; | ||
366 | limit_addr = GRANULEROUNDDOWN(limit_addr); | ||
367 | |||
368 | if (md->phys_addr > limit_addr) | ||
369 | continue; | ||
370 | |||
371 | md->num_pages = (limit_addr - md->phys_addr) >> | ||
372 | EFI_PAGE_SHIFT; | ||
373 | first_non_wb_addr = max_addr = md->phys_addr + | ||
374 | (md->num_pages << EFI_PAGE_SHIFT); | ||
375 | } | ||
376 | total_mem += (md->num_pages << EFI_PAGE_SHIFT); | ||
377 | |||
378 | if (md->num_pages == 0) | ||
379 | continue; | ||
380 | |||
381 | curr.start = PAGE_OFFSET + md->phys_addr; | ||
382 | curr.end = curr.start + (md->num_pages << EFI_PAGE_SHIFT); | ||
383 | |||
384 | if (!prev_valid) { | ||
385 | prev = curr; | ||
386 | prev_valid = 1; | ||
387 | } else { | ||
388 | if (curr.start < prev.start) | ||
389 | printk(KERN_ERR "Oops: EFI memory table not ordered!\n"); | ||
390 | |||
391 | if (prev.end == curr.start) { | ||
392 | /* merge two consecutive memory ranges */ | ||
393 | prev.end = curr.end; | ||
394 | } else { | ||
395 | start = PAGE_ALIGN(prev.start); | ||
396 | end = prev.end & PAGE_MASK; | ||
397 | if ((end > start) && (*callback)(start, end, arg) < 0) | ||
398 | return; | ||
399 | prev = curr; | ||
400 | } | ||
401 | } | ||
402 | } | ||
403 | } | ||
404 | if (prev_valid) { | ||
405 | start = PAGE_ALIGN(prev.start); | ||
406 | end = prev.end & PAGE_MASK; | ||
407 | if (end > start) | ||
408 | (*callback)(start, end, arg); | ||
409 | } | ||
410 | } | 276 | } |
411 | 277 | ||
412 | /* | 278 | /* |
413 | * Walk the EFI memory map to pull out leftover pages in the lower | 279 | * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that |
414 | * memory regions which do not end up in the regular memory map and | 280 | * has memory that is available for uncached allocator. |
415 | * stick them into the uncached allocator | ||
416 | * | ||
417 | * The regular walk function is significantly more complex than the | ||
418 | * uncached walk which means it really doesn't make sense to try and | ||
419 | * marge the two. | ||
420 | */ | 281 | */ |
421 | void __init | 282 | void |
422 | efi_memmap_walk_uc (efi_freemem_callback_t callback) | 283 | efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg) |
423 | { | 284 | { |
424 | void *efi_map_start, *efi_map_end, *p; | 285 | walk(callback, arg, EFI_MEMORY_UC); |
425 | efi_memory_desc_t *md; | ||
426 | u64 efi_desc_size, start, end; | ||
427 | |||
428 | efi_map_start = __va(ia64_boot_param->efi_memmap); | ||
429 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | ||
430 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | ||
431 | |||
432 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { | ||
433 | md = p; | ||
434 | if (md->attribute == EFI_MEMORY_UC) { | ||
435 | start = PAGE_ALIGN(md->phys_addr); | ||
436 | end = PAGE_ALIGN((md->phys_addr+(md->num_pages << EFI_PAGE_SHIFT)) & PAGE_MASK); | ||
437 | if ((*callback)(start, end, NULL) < 0) | ||
438 | return; | ||
439 | } | ||
440 | } | ||
441 | } | 286 | } |
442 | 287 | ||
443 | |||
444 | /* | 288 | /* |
445 | * Look for the PAL_CODE region reported by EFI and maps it using an | 289 | * Look for the PAL_CODE region reported by EFI and maps it using an |
446 | * ITR to enable safe PAL calls in virtual mode. See IA-64 Processor | 290 | * ITR to enable safe PAL calls in virtual mode. See IA-64 Processor |
@@ -862,3 +706,307 @@ efi_uart_console_only(void) | |||
862 | printk(KERN_ERR "Malformed %s value\n", name); | 706 | printk(KERN_ERR "Malformed %s value\n", name); |
863 | return 0; | 707 | return 0; |
864 | } | 708 | } |
709 | |||
710 | #define efi_md_size(md) (md->num_pages << EFI_PAGE_SHIFT) | ||
711 | |||
712 | static inline u64 | ||
713 | kmd_end(kern_memdesc_t *kmd) | ||
714 | { | ||
715 | return (kmd->start + (kmd->num_pages << EFI_PAGE_SHIFT)); | ||
716 | } | ||
717 | |||
718 | static inline u64 | ||
719 | efi_md_end(efi_memory_desc_t *md) | ||
720 | { | ||
721 | return (md->phys_addr + efi_md_size(md)); | ||
722 | } | ||
723 | |||
724 | static inline int | ||
725 | efi_wb(efi_memory_desc_t *md) | ||
726 | { | ||
727 | return (md->attribute & EFI_MEMORY_WB); | ||
728 | } | ||
729 | |||
730 | static inline int | ||
731 | efi_uc(efi_memory_desc_t *md) | ||
732 | { | ||
733 | return (md->attribute & EFI_MEMORY_UC); | ||
734 | } | ||
735 | |||
736 | /* | ||
737 | * Look for the first granule aligned memory descriptor memory | ||
738 | * that is big enough to hold EFI memory map. Make sure this | ||
739 | * descriptor is atleast granule sized so it does not get trimmed | ||
740 | */ | ||
741 | struct kern_memdesc * | ||
742 | find_memmap_space (void) | ||
743 | { | ||
744 | u64 contig_low=0, contig_high=0; | ||
745 | u64 as = 0, ae; | ||
746 | void *efi_map_start, *efi_map_end, *p, *q; | ||
747 | efi_memory_desc_t *md, *pmd = NULL, *check_md; | ||
748 | u64 space_needed, efi_desc_size; | ||
749 | unsigned long total_mem = 0; | ||
750 | |||
751 | efi_map_start = __va(ia64_boot_param->efi_memmap); | ||
752 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | ||
753 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | ||
754 | |||
755 | /* | ||
756 | * Worst case: we need 3 kernel descriptors for each efi descriptor | ||
757 | * (if every entry has a WB part in the middle, and UC head and tail), | ||
758 | * plus one for the end marker. | ||
759 | */ | ||
760 | space_needed = sizeof(kern_memdesc_t) * | ||
761 | (3 * (ia64_boot_param->efi_memmap_size/efi_desc_size) + 1); | ||
762 | |||
763 | for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) { | ||
764 | md = p; | ||
765 | if (!efi_wb(md)) { | ||
766 | continue; | ||
767 | } | ||
768 | if (pmd == NULL || !efi_wb(pmd) || efi_md_end(pmd) != md->phys_addr) { | ||
769 | contig_low = GRANULEROUNDUP(md->phys_addr); | ||
770 | contig_high = efi_md_end(md); | ||
771 | for (q = p + efi_desc_size; q < efi_map_end; q += efi_desc_size) { | ||
772 | check_md = q; | ||
773 | if (!efi_wb(check_md)) | ||
774 | break; | ||
775 | if (contig_high != check_md->phys_addr) | ||
776 | break; | ||
777 | contig_high = efi_md_end(check_md); | ||
778 | } | ||
779 | contig_high = GRANULEROUNDDOWN(contig_high); | ||
780 | } | ||
781 | if (!is_available_memory(md) || md->type == EFI_LOADER_DATA) | ||
782 | continue; | ||
783 | |||
784 | /* Round ends inward to granule boundaries */ | ||
785 | as = max(contig_low, md->phys_addr); | ||
786 | ae = min(contig_high, efi_md_end(md)); | ||
787 | |||
788 | /* keep within max_addr= command line arg */ | ||
789 | ae = min(ae, max_addr); | ||
790 | if (ae <= as) | ||
791 | continue; | ||
792 | |||
793 | /* avoid going over mem= command line arg */ | ||
794 | if (total_mem + (ae - as) > mem_limit) | ||
795 | ae -= total_mem + (ae - as) - mem_limit; | ||
796 | |||
797 | if (ae <= as) | ||
798 | continue; | ||
799 | |||
800 | if (ae - as > space_needed) | ||
801 | break; | ||
802 | } | ||
803 | if (p >= efi_map_end) | ||
804 | panic("Can't allocate space for kernel memory descriptors"); | ||
805 | |||
806 | return __va(as); | ||
807 | } | ||
808 | |||
809 | /* | ||
810 | * Walk the EFI memory map and gather all memory available for kernel | ||
811 | * to use. We can allocate partial granules only if the unavailable | ||
812 | * parts exist, and are WB. | ||
813 | */ | ||
814 | void | ||
815 | efi_memmap_init(unsigned long *s, unsigned long *e) | ||
816 | { | ||
817 | struct kern_memdesc *k, *prev = 0; | ||
818 | u64 contig_low=0, contig_high=0; | ||
819 | u64 as, ae, lim; | ||
820 | void *efi_map_start, *efi_map_end, *p, *q; | ||
821 | efi_memory_desc_t *md, *pmd = NULL, *check_md; | ||
822 | u64 efi_desc_size; | ||
823 | unsigned long total_mem = 0; | ||
824 | |||
825 | k = kern_memmap = find_memmap_space(); | ||
826 | |||
827 | efi_map_start = __va(ia64_boot_param->efi_memmap); | ||
828 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | ||
829 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | ||
830 | |||
831 | for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) { | ||
832 | md = p; | ||
833 | if (!efi_wb(md)) { | ||
834 | if (efi_uc(md) && (md->type == EFI_CONVENTIONAL_MEMORY || | ||
835 | md->type == EFI_BOOT_SERVICES_DATA)) { | ||
836 | k->attribute = EFI_MEMORY_UC; | ||
837 | k->start = md->phys_addr; | ||
838 | k->num_pages = md->num_pages; | ||
839 | k++; | ||
840 | } | ||
841 | continue; | ||
842 | } | ||
843 | if (pmd == NULL || !efi_wb(pmd) || efi_md_end(pmd) != md->phys_addr) { | ||
844 | contig_low = GRANULEROUNDUP(md->phys_addr); | ||
845 | contig_high = efi_md_end(md); | ||
846 | for (q = p + efi_desc_size; q < efi_map_end; q += efi_desc_size) { | ||
847 | check_md = q; | ||
848 | if (!efi_wb(check_md)) | ||
849 | break; | ||
850 | if (contig_high != check_md->phys_addr) | ||
851 | break; | ||
852 | contig_high = efi_md_end(check_md); | ||
853 | } | ||
854 | contig_high = GRANULEROUNDDOWN(contig_high); | ||
855 | } | ||
856 | if (!is_available_memory(md)) | ||
857 | continue; | ||
858 | |||
859 | /* | ||
860 | * Round ends inward to granule boundaries | ||
861 | * Give trimmings to uncached allocator | ||
862 | */ | ||
863 | if (md->phys_addr < contig_low) { | ||
864 | lim = min(efi_md_end(md), contig_low); | ||
865 | if (efi_uc(md)) { | ||
866 | if (k > kern_memmap && (k-1)->attribute == EFI_MEMORY_UC && | ||
867 | kmd_end(k-1) == md->phys_addr) { | ||
868 | (k-1)->num_pages += (lim - md->phys_addr) >> EFI_PAGE_SHIFT; | ||
869 | } else { | ||
870 | k->attribute = EFI_MEMORY_UC; | ||
871 | k->start = md->phys_addr; | ||
872 | k->num_pages = (lim - md->phys_addr) >> EFI_PAGE_SHIFT; | ||
873 | k++; | ||
874 | } | ||
875 | } | ||
876 | as = contig_low; | ||
877 | } else | ||
878 | as = md->phys_addr; | ||
879 | |||
880 | if (efi_md_end(md) > contig_high) { | ||
881 | lim = max(md->phys_addr, contig_high); | ||
882 | if (efi_uc(md)) { | ||
883 | if (lim == md->phys_addr && k > kern_memmap && | ||
884 | (k-1)->attribute == EFI_MEMORY_UC && | ||
885 | kmd_end(k-1) == md->phys_addr) { | ||
886 | (k-1)->num_pages += md->num_pages; | ||
887 | } else { | ||
888 | k->attribute = EFI_MEMORY_UC; | ||
889 | k->start = lim; | ||
890 | k->num_pages = (efi_md_end(md) - lim) >> EFI_PAGE_SHIFT; | ||
891 | k++; | ||
892 | } | ||
893 | } | ||
894 | ae = contig_high; | ||
895 | } else | ||
896 | ae = efi_md_end(md); | ||
897 | |||
898 | /* keep within max_addr= command line arg */ | ||
899 | ae = min(ae, max_addr); | ||
900 | if (ae <= as) | ||
901 | continue; | ||
902 | |||
903 | /* avoid going over mem= command line arg */ | ||
904 | if (total_mem + (ae - as) > mem_limit) | ||
905 | ae -= total_mem + (ae - as) - mem_limit; | ||
906 | |||
907 | if (ae <= as) | ||
908 | continue; | ||
909 | if (prev && kmd_end(prev) == md->phys_addr) { | ||
910 | prev->num_pages += (ae - as) >> EFI_PAGE_SHIFT; | ||
911 | total_mem += ae - as; | ||
912 | continue; | ||
913 | } | ||
914 | k->attribute = EFI_MEMORY_WB; | ||
915 | k->start = as; | ||
916 | k->num_pages = (ae - as) >> EFI_PAGE_SHIFT; | ||
917 | total_mem += ae - as; | ||
918 | prev = k++; | ||
919 | } | ||
920 | k->start = ~0L; /* end-marker */ | ||
921 | |||
922 | /* reserve the memory we are using for kern_memmap */ | ||
923 | *s = (u64)kern_memmap; | ||
924 | *e = (u64)++k; | ||
925 | } | ||
926 | |||
927 | void | ||
928 | efi_initialize_iomem_resources(struct resource *code_resource, | ||
929 | struct resource *data_resource) | ||
930 | { | ||
931 | struct resource *res; | ||
932 | void *efi_map_start, *efi_map_end, *p; | ||
933 | efi_memory_desc_t *md; | ||
934 | u64 efi_desc_size; | ||
935 | char *name; | ||
936 | unsigned long flags; | ||
937 | |||
938 | efi_map_start = __va(ia64_boot_param->efi_memmap); | ||
939 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | ||
940 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | ||
941 | |||
942 | res = NULL; | ||
943 | |||
944 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { | ||
945 | md = p; | ||
946 | |||
947 | if (md->num_pages == 0) /* should not happen */ | ||
948 | continue; | ||
949 | |||
950 | flags = IORESOURCE_MEM; | ||
951 | switch (md->type) { | ||
952 | |||
953 | case EFI_MEMORY_MAPPED_IO: | ||
954 | case EFI_MEMORY_MAPPED_IO_PORT_SPACE: | ||
955 | continue; | ||
956 | |||
957 | case EFI_LOADER_CODE: | ||
958 | case EFI_LOADER_DATA: | ||
959 | case EFI_BOOT_SERVICES_DATA: | ||
960 | case EFI_BOOT_SERVICES_CODE: | ||
961 | case EFI_CONVENTIONAL_MEMORY: | ||
962 | if (md->attribute & EFI_MEMORY_WP) { | ||
963 | name = "System ROM"; | ||
964 | flags |= IORESOURCE_READONLY; | ||
965 | } else { | ||
966 | name = "System RAM"; | ||
967 | } | ||
968 | break; | ||
969 | |||
970 | case EFI_ACPI_MEMORY_NVS: | ||
971 | name = "ACPI Non-volatile Storage"; | ||
972 | flags |= IORESOURCE_BUSY; | ||
973 | break; | ||
974 | |||
975 | case EFI_UNUSABLE_MEMORY: | ||
976 | name = "reserved"; | ||
977 | flags |= IORESOURCE_BUSY | IORESOURCE_DISABLED; | ||
978 | break; | ||
979 | |||
980 | case EFI_RESERVED_TYPE: | ||
981 | case EFI_RUNTIME_SERVICES_CODE: | ||
982 | case EFI_RUNTIME_SERVICES_DATA: | ||
983 | case EFI_ACPI_RECLAIM_MEMORY: | ||
984 | default: | ||
985 | name = "reserved"; | ||
986 | flags |= IORESOURCE_BUSY; | ||
987 | break; | ||
988 | } | ||
989 | |||
990 | if ((res = kcalloc(1, sizeof(struct resource), GFP_KERNEL)) == NULL) { | ||
991 | printk(KERN_ERR "failed to alocate resource for iomem\n"); | ||
992 | return; | ||
993 | } | ||
994 | |||
995 | res->name = name; | ||
996 | res->start = md->phys_addr; | ||
997 | res->end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1; | ||
998 | res->flags = flags; | ||
999 | |||
1000 | if (insert_resource(&iomem_resource, res) < 0) | ||
1001 | kfree(res); | ||
1002 | else { | ||
1003 | /* | ||
1004 | * We don't know which region contains | ||
1005 | * kernel data so we try it repeatedly and | ||
1006 | * let the resource manager test it. | ||
1007 | */ | ||
1008 | insert_resource(res, code_resource); | ||
1009 | insert_resource(res, data_resource); | ||
1010 | } | ||
1011 | } | ||
1012 | } | ||