static int smm_create_map(uintptr_t smbase, unsigned int num_cpus,
			const struct smm_loader_params *params)
{
	unsigned int i;
	struct rmodule smm_stub;
	unsigned int ss_size = params->per_cpu_save_state_size, stub_size;
	unsigned int smm_entry_offset = params->smm_main_entry_offset;
	unsigned int seg_count = 0, segments = 0, available;
	unsigned int cpus_in_segment = 0;
	unsigned int base = smbase;

	if (rmodule_parse(&_binary_smmstub_start, &smm_stub)) {
		printk(BIOS_ERR, "%s: unable to get SMM module size\n", __func__);
		return 0;
	}

	stub_size = rmodule_memory_size(&smm_stub);
	/* How many CPUs can fit into one 64K segment? */
	available = 0xFFFF - smm_entry_offset - ss_size - stub_size;
	if (available > 0) {
		cpus_in_segment = available / ss_size;
		/* minimum segments needed will always be 1 */
		segments = num_cpus / cpus_in_segment + 1;
		printk(BIOS_DEBUG,
			"%s: cpus allowed in one segment %d\n", __func__, cpus_in_segment);
		printk(BIOS_DEBUG,
			"%s: min # of segments needed %d\n", __func__, segments);
	} else {
		printk(BIOS_ERR, "%s: not enough space in SMM to setup all CPUs\n", __func__);
		printk(BIOS_ERR, "    save state & stub size need to be reduced\n");
		printk(BIOS_ERR, "    or increase SMRAM size\n");
		return 0;
	}

	if (sizeof(cpus) / sizeof(struct cpu_smm_info) < num_cpus) {
		printk(BIOS_ERR,
			"%s: increase MAX_CPUS in Kconfig\n", __func__);
		return 0;
	}

	for (i = 0; i < num_cpus; i++) {
		cpus[i].smbase = base;
		cpus[i].entry = base + smm_entry_offset;
		cpus[i].ss_start = cpus[i].entry + (smm_entry_offset - ss_size);
		cpus[i].code_start = cpus[i].entry;
		cpus[i].code_end = cpus[i].entry + stub_size;
		cpus[i].active = 1;
		base -= ss_size;
		seg_count++;
		if (seg_count >= cpus_in_segment) {
			base -= smm_entry_offset;
			seg_count = 0;
		}
	}

	if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) {
		seg_count = 0;
		for (i = 0; i < num_cpus; i++) {
			printk(BIOS_DEBUG, "CPU 0x%x\n", i);
			printk(BIOS_DEBUG,
				"    smbase %zx  entry %zx\n",
				cpus[i].smbase, cpus[i].entry);
			printk(BIOS_DEBUG,
				"           ss_start %zx  code_end %zx\n",
				cpus[i].ss_start, cpus[i].code_end);
			seg_count++;
			if (seg_count >= cpus_in_segment) {
				printk(BIOS_DEBUG,
					"-------------NEW CODE SEGMENT --------------\n");
				seg_count = 0;
			}
		}
	}
	return 1;
}
static int smm_create_map(uintptr_t smbase, unsigned int num_cpus,
			const struct smm_loader_params *params)
{
	unsigned int i;
	struct rmodule smm_stub;
	unsigned int ss_size = params->per_cpu_save_state_size, stub_size;
	unsigned int smm_entry_offset = params->smm_main_entry_offset;
	unsigned int seg_count = 0, segments = 0, available;
	unsigned int cpus_in_segment = 0;
	unsigned int base = smbase;

	if (rmodule_parse(&_binary_smmstub_start, &smm_stub)) {
		printk(BIOS_ERR, "%s: unable to get SMM module size\n", __func__);
		return 0;
	}

	stub_size = rmodule_memory_size(&smm_stub);
	 
	available = 0xFFFF - smm_entry_offset - ss_size - stub_size;
	if (available > 0) {
		cpus_in_segment = available / ss_size;
		 
		segments = num_cpus / cpus_in_segment + 1;
		printk(BIOS_DEBUG,
			"%s: cpus allowed in one segment %d\n", __func__, cpus_in_segment);
		printk(BIOS_DEBUG,
			"%s: min # of segments needed %d\n", __func__, segments);
	} else {
		printk(BIOS_ERR, "%s: not enough space in SMM to setup all CPUs\n", __func__);
		printk(BIOS_ERR, "    save state & stub size need to be reduced\n");
		printk(BIOS_ERR, "    or increase SMRAM size\n");
		return 0;
	}

	if (sizeof(cpus) / sizeof(struct cpu_smm_info) < num_cpus) {
		printk(BIOS_ERR,
			"%s: increase MAX_CPUS in Kconfig\n", __func__);
		return 0;
	}

	for (i = 0; i < num_cpus; i++) {
		cpus[i].smbase = base;
		cpus[i].entry = base + smm_entry_offset;
		cpus[i].ss_start = cpus[i].entry + (smm_entry_offset - ss_size);
		cpus[i].code_start = cpus[i].entry;
		cpus[i].code_end = cpus[i].entry + stub_size;
		cpus[i].active = 1;
		base -= ss_size;
		seg_count++;
		if (seg_count >= cpus_in_segment) {
			base -= smm_entry_offset;
			seg_count = 0;
		}
	}

	if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) {
		seg_count = 0;
		for (i = 0; i < num_cpus; i++) {
			printk(BIOS_DEBUG, "CPU 0x%x\n", i);
			printk(BIOS_DEBUG,
				"    smbase %zx  entry %zx\n",
				cpus[i].smbase, cpus[i].entry);
			printk(BIOS_DEBUG,
				"           ss_start %zx  code_end %zx\n",
				cpus[i].ss_start, cpus[i].code_end);
			seg_count++;
			if (seg_count >= cpus_in_segment) {
				printk(BIOS_DEBUG,
					"-------------NEW CODE SEGMENT --------------\n");
				seg_count = 0;
			}
		}
	}
	return 1;
}