+ if ((base + num - 1) > pnmax) {
+ num = pnmax - base + 1;
+ }
+ if (!num) {
+ continue;
+ }
+
+ switch (mptr->Type) {
+ // any kind of dram
+ case kEfiACPIMemoryNVS:
+ case kEfiPalCode:
+ non_os_pagecount += num;
+
+ // OS used dram
+ case kEfiLoaderCode:
+ case kEfiLoaderData:
+ case kEfiBootServicesCode:
+ case kEfiBootServicesData:
+ case kEfiConventionalMemory:
+
+ for (bank = 0; bank < num_banks; bank++) {
+ if (dram_ranges[bank].first_page <= base) {
+ continue;
+ }
+ if ((base + num) == dram_ranges[bank].first_page) {
+ dram_ranges[bank].first_page = base;
+ num = 0;
+ }
+ break;
+ }
+ if (!num) {
+ break;
+ }
+
+ if (bank && (base == (1 + dram_ranges[bank - 1].last_page))) {
+ bank--;
+ } else {
+ num_banks++;
+ if (num_banks >= MAX_BANKS) {
+ break;
+ }
+ bcopy(&dram_ranges[bank],
+ &dram_ranges[bank + 1],
+ (num_banks - bank - 1) * sizeof(hibernate_bitmap_t));
+ dram_ranges[bank].first_page = base;
+ }
+ dram_ranges[bank].last_page = base + num - 1;
+ break;
+
+ // runtime services will be restarted, so no save
+ case kEfiRuntimeServicesCode:
+ case kEfiRuntimeServicesData:
+ // contents are volatile once the platform expert starts
+ case kEfiACPIReclaimMemory:
+ // non dram
+ case kEfiReservedMemoryType:
+ case kEfiUnusableMemory:
+ case kEfiMemoryMappedIO:
+ case kEfiMemoryMappedIOPortSpace:
+ default:
+ break;
+ }
+ }
+
+ if (num_banks >= MAX_BANKS) {
+ HIBLOG("%s error, num_banks exceed MAX_BANKS(0x%x)\n", __FUNCTION__, MAX_BANKS);
+ return NULL;
+ }
+
+ // size the hibernation bitmap
+
+ size = sizeof(hibernate_page_list_t);
+ page_count = 0;
+ for (bank = 0; bank < num_banks; bank++) {
+ pages = dram_ranges[bank].last_page + 1 - dram_ranges[bank].first_page;
+ page_count += pages;
+ size += sizeof(hibernate_bitmap_t) + ((pages + 31) >> 5) * sizeof(uint32_t);
+ }
+
+ list = (hibernate_page_list_t *)kalloc(size);
+ if (!list) {
+ return list;
+ }
+
+ list->list_size = (uint32_t)size;
+ list->page_count = page_count;
+ list->bank_count = num_banks;
+
+ // convert to hibernation bitmap.
+
+ bitmap = &list->bank_bitmap[0];
+ for (bank = 0; bank < num_banks; bank++) {
+ bitmap->first_page = dram_ranges[bank].first_page;
+ bitmap->last_page = dram_ranges[bank].last_page;
+ bitmap->bitmapwords = (bitmap->last_page + 1
+ - bitmap->first_page + 31) >> 5;
+ if (log) {
+ kprintf("hib bank[%d]: 0x%x000 end 0x%xfff\n",
+ bank, bitmap->first_page, bitmap->last_page);