Пример #1
0
void WardenWin::Init(WorldSession* pClient, BigNumber* K)
{
    Client = pClient;
    // Generate Warden Key
    SHA1Randx WK(K->AsByteArray(), K->GetNumBytes());
    WK.generate(InputKey, 16);
    WK.generate(OutputKey, 16);
    /*
    Seed: 4D808D2C77D905C41A6380EC08586AFE (0x05 packet)
    Hash: 568C054C781A972A6037A2290C22B52571A06F4E (0x04 packet)
    Module MD5: 79C0768D657977D697E10BAD956CCED1
    New Client Key: 7F 96 EE FD A5 B6 3D 20 A4 DF 8E 00 CB F4 83 04
    New Server Key: C2 B7 AD ED FC CC A9 C2 BF B3 F8 56 02 BA 80 9B
    */
    uint8 mod_seed[16] = { 0x4D, 0x80, 0x8D, 0x2C, 0x77, 0xD9, 0x05, 0xC4, 0x1A, 0x63, 0x80, 0xEC, 0x08, 0x58, 0x6A, 0xFE };

    memcpy(Seed, mod_seed, 16);

    iCrypto.Init(InputKey);
    oCrypto.Init(OutputKey);
    sLog.outDebug("Server side warden for client %u initializing...", pClient->GetAccountId());
    sLog.outDebug("  C->S Key: %s", ByteArrayToHexStr(InputKey, 16).c_str());
    sLog.outDebug("  S->C Key: %s", ByteArrayToHexStr(OutputKey, 16).c_str());
    sLog.outDebug("  Seed: %s", ByteArrayToHexStr(Seed, 16).c_str());
    sLog.outDebug("Loading Module...");

    Module = GetModuleForClient(Client);

    sLog.outDebug("  Module Key: %s", ByteArrayToHexStr(Module->Key, 16).c_str());
    sLog.outDebug("  Module ID: %s", ByteArrayToHexStr(Module->ID, 16).c_str());
    RequestModule();
}
Пример #2
0
void WardenMac::Init(WorldSession* pClient, BigNumber* K)
{
    Client = pClient;
    // Generate Warden Key
    SHA1Randx WK(K->AsByteArray(), K->GetNumBytes());
    WK.generate(InputKey, 16);
    WK.generate(OutputKey, 16);

    uint8 mod_seed[16] = { 0x4D, 0x80, 0x8D, 0x2C, 0x77, 0xD9, 0x05, 0xC4, 0x1A, 0x63, 0x80, 0xEC, 0x08, 0x58, 0x6A, 0xFE };

    memcpy(Seed, mod_seed, 16);

    iCrypto.Init(InputKey);
    oCrypto.Init(OutputKey);
    sLog->outStaticDebug("Server side warden for client %u initializing...", pClient->GetAccountId());
    //PrintHexArray("  C->S Key: ", InputKey, 16, true);
    //PrintHexArray("  S->C Key: ", OutputKey, 16, true);
    //PrintHexArray("  Seed: ", Seed, 16, true);
    sLog->outStaticDebug("Loading Module...");

    Module = GetModuleForClient();

    PrintHexArray("  Module Key: ", Module->Key, 16, true);
    PrintHexArray("  Module ID: ", Module->ID, 16, true);
    RequestModule();
}
Пример #3
0
void WardenMac::Init(WorldSession *pClient, BigNumber *K)
{
    Client = pClient;
    // Generate Warden Key
    SHA1Randx WK(K->AsByteArray(), K->GetNumBytes());
    WK.generate(InputKey, 16);
    WK.generate(OutputKey, 16);
    /*
    Seed: 4D808D2C77D905C41A6380EC08586AFE (0x05 packet)
    Hash: <?> (0x04 packet)
    Module MD5: 0DBBF209A27B1E279A9FEC5C168A15F7
    New Client Key: <?>
    New Server Key: <?>
    */
    uint8 mod_seed[16] = { 0x4D, 0x80, 0x8D, 0x2C, 0x77, 0xD9, 0x05, 0xC4, 0x1A, 0x63, 0x80, 0xEC, 0x08, 0x58, 0x6A, 0xFE };

    memcpy(Seed, mod_seed, 16);

    iCrypto.Init(InputKey);
    oCrypto.Init(OutputKey);
    sLog.outDebug("Server side warden for client %u initializing...", pClient->GetAccountId());
    sLog.outDebug("  C->S Key: %s", ByteArrayToHexStr(InputKey, 16).c_str());
    sLog.outDebug("  S->C Key: %s", ByteArrayToHexStr(OutputKey, 16).c_str());
    sLog.outDebug("  Seed: %s", ByteArrayToHexStr(Seed, 16).c_str());
    sLog.outDebug("Loading Module...");

    Module = GetModuleForClient(Client);

    sLog.outDebug("  Module Key: %s", ByteArrayToHexStr(Module->Key, 16).c_str());
    sLog.outDebug("  Module ID: %s", ByteArrayToHexStr(Module->ID, 16).c_str());
    RequestModule();
}
Пример #4
0
void WardenWin::Init(WorldSession* session, BigNumber *k)
{
    _session = session;
    // Generate Warden Key
    SHA1Randx WK(k->AsByteArray().get(), k->GetNumBytes());
    WK.Generate(_inputKey, 16);
    WK.Generate(_outputKey, 16);

    memcpy(_seed, Module.Seed, 16);

    _inputCrypto.Init(_inputKey);
    _outputCrypto.Init(_outputKey);
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
    sLog->outDebug(LOG_FILTER_WARDEN, "Server side warden for client %u initializing...", session->GetAccountId());
    sLog->outDebug(LOG_FILTER_WARDEN, "C->S Key: %s", ByteArrayToHexStr(_inputKey, 16).c_str());
    sLog->outDebug(LOG_FILTER_WARDEN, "S->C Key: %s", ByteArrayToHexStr(_outputKey, 16).c_str());
    sLog->outDebug(LOG_FILTER_WARDEN, "  Seed: %s", ByteArrayToHexStr(_seed, 16).c_str());
    sLog->outDebug(LOG_FILTER_WARDEN, "Loading Module...");
#endif

    _module = GetModuleForClient();

#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
    sLog->outDebug(LOG_FILTER_WARDEN, "Module Key: %s", ByteArrayToHexStr(_module->Key, 16).c_str());
    sLog->outDebug(LOG_FILTER_WARDEN, "Module ID: %s", ByteArrayToHexStr(_module->Id, 16).c_str());
#endif
    RequestModule();
}
Пример #5
0
void WardenMac::Init(WorldSession* pClient, BigNumber* K)
{
    _session = pClient;
    // Generate Warden Key
    SessionKeyGenerator<SHA1Hash> WK(K->AsByteArray().get(), K->GetNumBytes());
    WK.Generate(_inputKey, 16);
    WK.Generate(_outputKey, 16);
    /*
    Seed: 4D808D2C77D905C41A6380EC08586AFE (0x05 packet)
    Hash: <?> (0x04 packet)
    Module MD5: 0DBBF209A27B1E279A9FEC5C168A15F7
    New Client Key: <?>
    New Cerver Key: <?>
    */
    uint8 mod_seed[16] = { 0x4D, 0x80, 0x8D, 0x2C, 0x77, 0xD9, 0x05, 0xC4, 0x1A, 0x63, 0x80, 0xEC, 0x08, 0x58, 0x6A, 0xFE };

    memcpy(_seed, mod_seed, 16);

    _inputCrypto.Init(_inputKey);
    _outputCrypto.Init(_outputKey);
    TC_LOG_DEBUG("warden", "Server side warden for client %u initializing...", pClient->GetAccountId());
    TC_LOG_DEBUG("warden", "C->S Key: %s", ByteArrayToHexStr(_inputKey, 16).c_str());
    TC_LOG_DEBUG("warden", "S->C Key: %s", ByteArrayToHexStr(_outputKey, 16).c_str());
    TC_LOG_DEBUG("warden", "  Seed: %s", ByteArrayToHexStr(_seed, 16).c_str());
    TC_LOG_DEBUG("warden", "Loading Module...");

    _module = GetModuleForClient();

    TC_LOG_DEBUG("warden", "Module Key: %s", ByteArrayToHexStr(_module->Key, 16).c_str());
    TC_LOG_DEBUG("warden", "Module ID: %s", ByteArrayToHexStr(_module->Id, 16).c_str());
    RequestModule();
}
Пример #6
0
void WardenWin::Init(WorldSession* session, BigNumber* k)
{
    _session = session;
    // Generate Warden Key
    SHA1Randx WK(k->AsByteArray().get(), k->GetNumBytes());
    WK.Generate(_inputKey, 16);
    WK.Generate(_outputKey, 16);

    memcpy(_seed, Module.Seed, 16);

    _inputCrypto.Init(_inputKey);
    _outputCrypto.Init(_outputKey);
    TC_LOG_DEBUG("warden", "Server side warden for client %u initializing...", session->GetAccountId());
    TC_LOG_DEBUG("warden", "C->S Key: %s", ByteArrayToHexStr(_inputKey, 16).c_str());
    TC_LOG_DEBUG("warden", "S->C Key: %s", ByteArrayToHexStr(_outputKey, 16).c_str());
    TC_LOG_DEBUG("warden", "  Seed: %s", ByteArrayToHexStr(_seed, 16).c_str());
    TC_LOG_DEBUG("warden", "Loading Module...");

    _module = GetModuleForClient();

    TC_LOG_DEBUG("warden", "Module Key: %s", ByteArrayToHexStr(_module->Key, 16).c_str());
    TC_LOG_DEBUG("warden", "Module ID: %s", ByteArrayToHexStr(_module->Id, 16).c_str());
    RequestModule();
}
MV1(WK(PAD1_SYS_BOOT7),		OFF_PU | OFF_IN | OFF_EN | IEN | M3)				\
MV(CP(DPM_EMU0),		M3)								\
MV(CP(DPM_EMU1),		M3)								\
MV(CP(DPM_EMU2),		IEN  | PTD | M7)							\
MV(CP(DPM_EMU3),		M3)							\
MV(CP(DPM_EMU4),		M3)							\
MV(CP(DPM_EMU5),		OFF_WE | OFF_PU | OFF_IN | OFF_EN | IEN | M3)		\
MV(CP(DPM_EMU6),		PTU | M2) 						\
MV(CP(DPM_EMU7),		PTU | IEN | M2)						\
MV(CP(DPM_EMU8),		PTD | M2)  						\
MV(CP(DPM_EMU9),		PTD | IEN | M2)						\
MV(CP(DPM_EMU10),		OFF_WE | IEN  | PTU | M3)				 			\
MV(CP(DPM_EMU11),		PTD | OFF_EN | OFF_PD | OFF_OUT_PTD | M3)		\
MV(CP(DPM_EMU12),		PTD | OFF_EN | OFF_PD | OFF_OUT_PTD | M3)		\
MV(CP(DPM_EMU13),		M3)							\
MV(CP(DPM_EMU14),		M3)								\
MV(CP(DPM_EMU15),		OFF_WE | PTD | IEN | M3)				\
MV(CP(DPM_EMU16),		M3)								\
MV(CP(DPM_EMU17),		OFF_EN | OFF_PD | OFF_OUT_PTD | IEN | M3)			\
MV(CP(DPM_EMU18),		M1)							\
MV(CP(DPM_EMU19),		M3)								\

#if	0

	MV1(WK(PAD1_JTAG_TCK) , ( IEN | M0))   \
	MV1(WK(PAD0_JTAG_RTCK) , ( M0))   \
	MV1(WK(PAD1_JTAG_TMS_TMSC) , ( IEN | M0))   \
	MV1(WK(PAD0_JTAG_TDI) , ( IEN | M0))   \
	MV1(WK(PAD1_JTAG_TDO) , ( M0))  
#endif
MV(CP(ABE_DMIC_DIN2),		OFF_EN | PTU | M3)				 \
MV(CP(ABE_DMIC_DIN3),		PTD | M3)					 \
MV(CP(UART2_CTS),		PTU | IEN | M0)					 	\
MV(CP(UART2_RTS),		M0)							\
MV(CP(UART2_RX),		PTU | IEN | M0)						\
MV(CP(UART2_TX),		M0)							\
MV(CP(HDQ_SIO),			M3)								\
MV(CP(I2C1_SCL),		PTU | IEN | M0)  						\
MV(CP(I2C1_SDA),		PTU | IEN | M0)  						\
MV(CP(I2C2_SCL),		PTU | IEN | M0)  						\
MV(CP(I2C2_SDA),		PTU | IEN | M0)  						\
MV(CP(I2C3_SCL),		PTU | IEN | M0)  						\
MV(CP(I2C3_SDA),		PTU | IEN | M0)  						\
MV(CP(I2C4_SCL),		PTU | IEN | M0)  						\
MV(CP(I2C4_SDA),		PTU | IEN | M0)  						\
MV1(WK(PAD1_SR_SCL),		PTU | IEN | M0)  						\
MV1(WK(PAD0_SR_SDA),		PTU | IEN | M0)							\
MV(CP(MCSPI1_CLK) 	, (IEN | PTD | DIS | M0))   \
MV(CP(MCSPI1_SOMI) 	, (IEN | PTD | DIS | M0))   \
MV(CP(MCSPI1_SIMO) 	, (IEN | PTD | DIS | M0))   \
MV(CP(MCSPI1_CS0) 	, (IEN | PTD | DIS | M0))   \
MV(CP(MCSPI1_CS1),		PTU | IEN | M1)						\
MV(CP(MCSPI1_CS2),		IEN  | PTD | M7)							\
MV(CP(MCSPI1_CS3),		M3)							\
MV(CP(UART3_CTS_RCTX),		M1)							\
MV(CP(UART3_RTS_SD),		IEN  | PTD | M7)							\
MV(CP(UART3_RX_IRRX),		M1)								\
MV(CP(UART3_TX_IRTX),		M3)								\
MV(CP(SDMMC5_CLK),		OFF_EN | OFF_OUT_PTU | IEN | PTU | M0)				\
MV(CP(SDMMC5_CMD),		OFF_EN | OFF_PU | OFF_IN | IEN | PTU | M0)  			\
MV(CP(SDMMC5_DAT0),		OFF_EN | OFF_PU | OFF_IN | IEN | PTU | M0)  		\
};

#define OMAP4_GPIO_OE			0x0134
#define OMAP4_GPIO_CLEARDATAOUT		0x0190
#define OMAP4_GPIO_SETDATAOUT		0x0194
#define OMAP4_GPIO_DATAIN               0x0138


// giant table to map gpio numbers to their pin's pad configuration addresses
#define		OMAP44XX_WKUP_CTRL_BASE		0x4A31E000
#define		CP(x)	(OMAP44XX_CTRL_BASE + CONTROL_PADCONF_##x)
#define		WK(x)	(OMAP44XX_WKUP_CTRL_BASE + CONTROL_WKUP_##x)
#define		INVALID_PADCONF_VALUE 0x00000000

static u32 gpio_padconf_map[] = {
	WK(PAD0_SIM_IO),		// gpio_wk0
	WK(PAD1_SIM_CLK),
	WK(PAD0_SIM_RESET),
	WK(PAD1_SIM_CD),
	WK(PAD0_SIM_PWRCTRL),		// gpio_wk4
	WK(PAD0_FREF_SLICER_IN),
	WK(PAD0_FREF_CLK0_OUT),
	WK(PAD1_FREF_CLK4_REQ),		// gpio_wk7
	WK(PAD0_FREF_CLK4_OUT),
	WK(PAD0_SYS_BOOT6),
	WK(PAD1_SYS_BOOT7),		// gpio_wk10
	CP(DPM_EMU0),			// gpio_11
	CP(DPM_EMU1),
	CP(DPM_EMU2),
	CP(DPM_EMU3),
	CP(DPM_EMU4),
Пример #10
0
void start_armboot (void)
{
  	init_fnc_t **init_fnc_ptr;
	uchar *buf;
	char boot_dev_name[8];
	u32 si_type, omap4_rev;
	int len = 0;
	u8 val = SWITCH_OFF;
	image_type image;
 
   	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
		if ((*init_fnc_ptr)() != 0) {
			hang ();
		}
	}

	image.image = 2;
        image.val =99;

	omap4_rev = omap_revision();
	if (omap4_rev >= OMAP4460_ES1_0) {
		omap_temp_sensor_check();
		if (omap4_rev == OMAP4470_ES1_0) {
			writel(((TSHUT_HIGH_ADC_CODE << 16) |
			TSHUT_COLD_ADC_CODE), CORE_TSHUT_THRESHOLD);
			MV1(WK(CONTROL_SPARE_RW) , (M1));
		}
		si_type = omap4_silicon_type();
		if (si_type == PROD_ID_1_SILICON_TYPE_HIGH_PERF)
			printf("OMAP4470: 1.5 GHz capable SOM\n");
		else if (si_type == PROD_ID_1_SILICON_TYPE_STD_PERF)
			printf("OMAP4470: 1.3 GHz capable SOM\n");
	}
#ifdef CONFIG_USBBOOT_ERASER
	/* Erase mlo and poweroff */
	mlo_erase();
#else

#ifdef CONFIG_USBBOOT
	/*usb boot does not check power button */
	printf("boot_device=0x%x boot_mode=0x%x\n", get_boot_device(), get_boot_mode());
	printf("id_code=%08x\n", readl(CONTROL_ID_CODE));
#endif

#ifdef CONFIG_USBOOT_MEMTEST
	/* the device will power off after the test */
	mem_test();
	/*power off  PMIC */
	printf("Memtest done, powering off!\n");
	select_bus(CFG_I2C_BUS, CFG_I2C_SPEED);
	val = SWITCH_OFF;
	i2c_write(TWL6030_PMC_ID, PHOENIX_DEV_ON, 1, &val, 1);
	/* we should never get here */
	hang();
#endif

#ifdef START_LOADB_DOWNLOAD
	strcpy(boot_dev_name, "UART");
	do_load_serial_bin (CFG_LOADADDR, 115200);
#else
	buf = (uchar *) (CFG_LOADADDR - 0x120);
	image.data = (uchar *) (CFG_LOADADDR - 0x120);

	switch (get_boot_device()) {
#ifdef CONFIG_USBBOOT
	case 0x45:
		printf("boot_dev=USB\n");
		strcpy(boot_dev_name, "USB");
		/* read data from usb and write to sdram */
		if (usb_read_bootloader(&len) != 0) {
			hang();
		}
		printf("usb read len=%d\n", len);
		break;
#else
	case 0x03:
		strcpy(boot_dev_name, "ONENAND");
#if defined(CFG_ONENAND)
		for (i = ONENAND_START_BLOCK; i < ONENAND_END_BLOCK; i++) {
			if (!onenand_read_block(buf, i))
				buf += ONENAND_BLOCK_SIZE;
			else
				goto error;
		}
#endif
		break;
	case 0x02:
	default:
		strcpy(boot_dev_name, "NAND");
#if defined(CFG_NAND)
		for (i = NAND_UBOOT_START; i < NAND_UBOOT_END;
				i+= NAND_BLOCK_SIZE) {
			if (!nand_read_block(buf, i))
				buf += NAND_BLOCK_SIZE; /* advance buf ptr */
		}
#endif
		break;
	case 0x05:
		strcpy(boot_dev_name, "MMC/SD1");
#if defined(CONFIG_MMC)
		if (mmc_read_bootloader(0) != 0)
			goto error;
#endif
		break;
	case 0x06:
		strcpy(boot_dev_name, "EMMC");
#if defined(CONFIG_MMC)
		if (mmc_read_bootloader(1) != 0)
			goto error;
#endif
		break;
#endif	/* CONFIG_USBBOOT */
	};
#endif
	SEC_ENTRY_Std_Ppa_Call ( PPA_SERV_HAL_BN_CHK , 1 , &image );
 
	if ( image.val == 0 ) {
		/* go run U-Boot and never return */
		printf("Starting OS Bootloader from %s ...\n", boot_dev_name);
		((init_fnc_t *)CFG_LOADADDR)();
	}

	/* should never come here */
#if defined(CFG_ONENAND) || defined(CONFIG_MMC)
error:
#endif
	printf("Could not read bootloader!\n");
	hang();
#endif   /* CONFIG_USBBOOT_ERASER */	
}
Пример #11
0
void start_armboot (void)
{
  	init_fnc_t **init_fnc_ptr;
	uchar *buf;
	char boot_dev_name[8];
	u32 si_type, omap4_rev;
 
   	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
		if ((*init_fnc_ptr)() != 0) {
			hang ();
		}
	}

	omap4_rev = omap_revision();
	if (omap4_rev >= OMAP4460_ES1_0) {
		omap_temp_sensor_check();
		if (omap4_rev == OMAP4470_ES1_0) {
			writel(((TSHUT_HIGH_ADC_CODE << 16) |
			TSHUT_COLD_ADC_CODE), CORE_TSHUT_THRESHOLD);
			MV1(WK(CONTROL_SPARE_RW) , (M1));
		}
		si_type = omap4_silicon_type();
		if (si_type == PROD_ID_1_SILICON_TYPE_HIGH_PERF)
			printf("OMAP4460: 1.5 GHz capable SOM\n");
		else if (si_type == PROD_ID_1_SILICON_TYPE_STD_PERF)
			printf("OMAP4460: 1.2 GHz capable SOM\n");
	}
#ifdef START_LOADB_DOWNLOAD
	strcpy(boot_dev_name, "UART");
	do_load_serial_bin (CFG_LOADADDR, 115200);
#else
	buf = (uchar *) CFG_LOADADDR;

	switch (get_boot_device()) {
	case 0x03:
		strcpy(boot_dev_name, "ONENAND");
#if defined(CFG_ONENAND)
		for (i = ONENAND_START_BLOCK; i < ONENAND_END_BLOCK; i++) {
			if (!onenand_read_block(buf, i))
				buf += ONENAND_BLOCK_SIZE;
			else
				goto error;
		}
#endif
		break;
	case 0x02:
	default:
		strcpy(boot_dev_name, "NAND");
#if defined(CFG_NAND)
		for (i = NAND_UBOOT_START; i < NAND_UBOOT_END;
				i+= NAND_BLOCK_SIZE) {
			if (!nand_read_block(buf, i))
				buf += NAND_BLOCK_SIZE; /* advance buf ptr */
		}
#endif
		break;
	case 0x05:
		strcpy(boot_dev_name, "MMC/SD1");
#if defined(CONFIG_MMC)
		if (mmc_read_bootloader(0) != 0)
			goto error;
#endif
		break;
	case 0x06:
		strcpy(boot_dev_name, "EMMC");
#if defined(CONFIG_MMC)
		if (mmc_read_bootloader(1) != 0)
			goto error;
#endif
		break;
	};
#endif
	/* go run U-Boot and never return */
	printf("Starting OS Bootloader from %s ...\n", boot_dev_name);
 	((init_fnc_t *)CFG_LOADADDR)();

	/* should never come here */
#if defined(CFG_ONENAND) || defined(CONFIG_MMC)
error:
#endif
	printf("Could not read bootloader!\n");
	hang();
}
Пример #12
0
void cubgcv(
  double *x, double *f, double *df, int *n, double *y, double *c, int *ic,
  double *var, int *job, double *se, double *wk, int *ier)
{
  double delta, err, gf1, gf2, gf3, gf4, r1, r2, r3, r4, tau = 1.618033989;
  double ratio = 2.0, avh, avdf = 0.0, avar, stat[6], p, q;

  int done = 0, i;

/* Initialize */
  *ier = 133;
  if (*job >= 0 && *job <= 1)
    {
      spint1(x, &avh, f, df, &avdf, n, y, c, ic, wk, &WK(0, 3), ier);
      if (*ier == 0)
	{
	  avar = *var;
	  if (*var > 0)
	    avar = *var * avdf * avdf;

/* Check for zero variance */
	  if (fabs(*var) > DEPS)
	    {

/* Find local minimum of gcv or the expected mean square error */
	      r1 = 1;
	      r2 = ratio * r1;
	      spfit1(x, &avh, df, n, &r2, &p, &q, &gf2, &avar, stat, y, c, ic,
		     wk, &WK(0, 3), &WK(0, 5), &WK(0, 6));
	      do
		{
		  spfit1(x, &avh, df, n, &r1, &p, &q, &gf1, &avar,
			 stat, y, c, ic, wk, &WK(0, 3), &WK(0, 5), &WK(0, 6));
		  if (gf2 > gf1)
		    {
/* Exit if p zero */
		      if (p > 0)
			{
			  r2 = r1;
			  gf2 = gf1;
			  r1 /= ratio;
			}
		      else
			done = 1;
		    }
		}
	      while (gf2 > gf1 && p > 0);

	      if (!done)
		{
		  r3 = ratio * r2;
		  do
		    {
		      spfit1(x, &avh, df, n, &r3, &p, &q, &gf3, &avar, stat,
			     y, c, ic, wk, &WK(0, 3), &WK(0, 5), &WK(0, 6));
		      if (gf2 > gf3)
			{
/* Exit if q zero */
			  if (q > 0)
			    {
			      r2 = r3;
			      gf2 = gf3;
			      r3 *= ratio;
			    }
			  else
			    done = 1;
			}
		    }
		  while (gf2 > gf3 && q > 0);
		}

	      if (!done)
		{
		  r2 = r3;
		  gf2 = gf3;
		  delta = (r2 - r1) / tau;
		  r4 = r1 + delta;
		  r3 = r2 - delta;
		  spfit1(x, &avh, df, n, &r3, &p, &q, &gf3, &avar, stat,
			 y, c, ic, wk, &WK(0, 3), &WK(0, 5), &WK(0, 6));
		  spfit1(x, &avh, df, n, &r4, &p, &q, &gf4, &avar, stat,
			 y, c, ic, wk, &WK(0, 3), &WK(0, 5), &WK(0, 6));
		  do
		    {

/* Golden section search for local minimum */
		      if (gf3 > gf4)
			{
			  r1 = r3;
			  gf1 = gf3;
			  r3 = r4;
			  gf3 = gf4;
			  delta /= tau;
			  r4 = r1 + delta;
			  spfit1(x, &avh, df, n, &r4, &p, &q, &gf4, &avar, stat,
				 y, c, ic, wk, &WK(0, 3), &WK(0, 5), &WK(0, 6));
			}
		      else
			{
			  r2 = r4;
			  gf2 = gf4;
			  r4 = r3;
			  gf4 = gf3;
			  delta /= tau;
			  r3 = r2 - delta;
			  spfit1(x, &avh, df, n, &r3, &p, &q, &gf3, &avar, stat,
				 y, c, ic, wk, &WK(0, 3), &WK(0, 5), &WK(0, 6));
			}
		      err = (r2 - r1) / (r1 + r2);
		    }
		  while (err * err + 1 > 1 && err > 1E-6);
		  r1 = (r1 + r2) * 0.5;
		}
	    }
	  else
	    r1 = 0;

/* Calculate spline coefficients */
	  spfit1(x, &avh, df, n, &r1, &p, &q, &gf1, &avar, stat, y, c, ic,
		 wk, &WK(0, 3), &WK(0, 5), &WK(0, 6));
	  spcof1(x, &avh, f, df, n, &p, &q, y, c, ic, &WK(0, 5), &WK(0, 6));

/* Optionally calculate standard error estimates */
	  if (*var < 0)
	    {
	      avar = stat[5];
	      *var = avar / (avdf * avdf);
	    }
	  if (*job == 1)
	    sperr1(x, &avh, df, n, wk, &p, &avar, se);

/* Unscale df */
	  for (i = 0; i < *n; i++)
	    df[i] = df[i] * avdf;

/* Put statistics in wk */
	  for (i = 0; i < 6; i++)
	    WK(i, 0) = stat[i];
	  WK(5, 0) = stat[5] / (avdf * avdf);
	  WK(7, 0) = avdf * avdf;
	}
    }
}