Exemple #1
0
void
reboot(void *entry, void *code, ulong size)
{
	void (*f)(ulong, ulong, ulong);
	ulong *pdb;

	writeconf();

	/*
	 * the boot processor is cpu0.  execute this function on it
	 * so that the new kernel has the same cpu0.  this only matters
	 * because the hardware has a notion of which processor was the
	 * boot processor and we look at it at start up.
	 */
	if (m->machno != 0) {
		procwired(up, 0);
		sched();
	}

	shutdown(0);

	/*
	 * should be the only processor running now
	 */
	if (m->machno != 0)
		print("on cpu%d (not 0)!\n", m->machno);
	if (active.machs)
		print("still have active ap processors!\n");

	print("shutting down...\n");
	delay(200);

	splhi();

	/* turn off buffered serial console */
	serialoq = nil;

	/* shutdown devices */
	chandevshutdown();
	arch->introff();

	/*
	 * Modify the machine page table to directly map the low 4MB of memory
	 * This allows the reboot code to turn off the page mapping
	 */
	pdb = m->pdb;
	pdb[PDX(0)] = pdb[PDX(KZERO)];
	mmuflushtlb(PADDR(pdb));

	/* setup reboot trampoline function */
	f = (void*)REBOOTADDR;
	memmove(f, rebootcode, sizeof(rebootcode));

	print("rebooting...\n");

	/* off we go - never to return */
	coherence();
	(*f)(PADDR(entry), PADDR(code), size);
}
Exemple #2
0
/*
 * the new kernel is already loaded at address `code'
 * of size `size' and entry point `entry'.
 */
void
reboot(void *entry, void *code, ulong size)
{
	void (*f)(ulong, ulong, ulong);

	iprint("starting reboot...");
	writeconf();
	
	shutdown(0);

	/*
	 * should be the only processor running now
	 */

	print("shutting down...\n");
	delay(200);

	/* turn off buffered serial console */
	serialoq = nil;

	/* shutdown devices */
	chandevshutdown();

	/* call off the dog */
	clockshutdown();

	splhi();

	/* setup reboot trampoline function */
	f = (void*)REBOOTADDR;
	memmove(f, rebootcode, sizeof(rebootcode));
	cacheuwbinv();
	l2cacheuwb();

	print("rebooting...");
	iprint("entry %#lux code %#lux size %ld\n",
		PADDR(entry), PADDR(code), size);
	delay(100);		/* wait for uart to quiesce */

	/* off we go - never to return */
	cacheuwbinv();
	l2cacheuwb();
	(*f)(PADDR(entry), PADDR(code), size);

	iprint("loaded kernel returned!\n");
	delay(1000);
	archreboot();
}
Exemple #3
0
void CONFIG::Run(void) {
	static const char* const params[] = {
		"-r", "-wcp", "-wcd", "-wc", "-writeconf", "-l", "-rmconf",
		"-h", "-help", "-?", "-axclear", "-axadd", "-axtype", "-get", "-set",
		"-writelang", "-wl", "-securemode", "" };
	enum prs {
		P_NOMATCH, P_NOPARAMS, // fixed return values for GetParameterFromList
		P_RESTART,
		P_WRITECONF_PORTABLE, P_WRITECONF_DEFAULT, P_WRITECONF, P_WRITECONF2,
		P_LISTCONF,	P_KILLCONF,
		P_HELP, P_HELP2, P_HELP3,
		P_AUTOEXEC_CLEAR, P_AUTOEXEC_ADD, P_AUTOEXEC_TYPE,
		P_GETPROP, P_SETPROP,
		P_WRITELANG, P_WRITELANG2,
		P_SECURE
	} presult = P_NOMATCH;
	
	bool first = true;
	std::vector<std::string> pvars;
	// Loop through the passed parameters
	while(presult != P_NOPARAMS) {
		presult = (enum prs)cmd->GetParameterFromList(params, pvars);
		switch(presult) {
		
		case P_RESTART:
			if (securemode_check()) return;
			if (pvars.size() == 0) restart_program(control->startup_params);
			else {
				std::vector<std::string> restart_params;
				restart_params.push_back(control->cmdline->GetFileName());
				for(size_t i = 0; i < pvars.size(); i++) {
					restart_params.push_back(pvars[i]);
					if (pvars[i].find(' ') != std::string::npos) {
						pvars[i] = "\""+pvars[i]+"\""; // add back spaces
					}
				}
				// the rest on the commandline, too
				cmd->FillVector(restart_params);
				restart_program(restart_params);
			}
			return;
		
		case P_LISTCONF: {
			Bitu size = control->configfiles.size();
			std::string config_path;
			Cross::GetPlatformConfigDir(config_path);
			WriteOut(MSG_Get("PROGRAM_CONFIG_CONFDIR"), VERSION,config_path.c_str());
			if (size==0) WriteOut(MSG_Get("PROGRAM_CONFIG_NOCONFIGFILE"));
			else {
				WriteOut(MSG_Get("PROGRAM_CONFIG_PRIMARY_CONF"),control->configfiles.front().c_str());
				if (size > 1) {
					WriteOut(MSG_Get("PROGRAM_CONFIG_ADDITIONAL_CONF"));
					for(Bitu i = 1; i < size; i++)
						WriteOut("%s\n",control->configfiles[i].c_str());
				}
			}
			if (control->startup_params.size() > 0) {
				std::string test;
				for(size_t k = 0; k < control->startup_params.size(); k++)
					test += control->startup_params[k] + " ";
				WriteOut(MSG_Get("PROGRAM_CONFIG_PRINT_STARTUP"), test.c_str());
			}
			break;
		}
		case P_WRITECONF: case P_WRITECONF2:
			if (securemode_check()) return;
			if (pvars.size() > 1) return;
			else if (pvars.size() == 1) {
				// write config to specific file, except if it is an absolute path
				writeconf(pvars[0], !Cross::IsPathAbsolute(pvars[0]));
			} else {
				// -wc without parameter: write primary config file
				if (control->configfiles.size()) writeconf(control->configfiles[0], false);
				else WriteOut(MSG_Get("PROGRAM_CONFIG_NOCONFIGFILE"));
			}
			break;
		case P_WRITECONF_DEFAULT: {
			// write to /userdir/dosbox0.xx.conf
			if (securemode_check()) return;
			if (pvars.size() > 0) return;
			std::string confname;
			Cross::GetPlatformConfigName(confname);
			writeconf(confname, true);
			break;
		}
		case P_WRITECONF_PORTABLE:
			if (securemode_check()) return;
			if (pvars.size() > 1) return;
			else if (pvars.size() == 1) {
				// write config to startup directory
				writeconf(pvars[0], false);
			} else {
				// -wcp without parameter: write dosbox.conf to startup directory
				if (control->configfiles.size()) writeconf(std::string("dosbox.conf"), false);
				else WriteOut(MSG_Get("PROGRAM_CONFIG_NOCONFIGFILE"));
			}
			break;

		case P_NOPARAMS:
			if (!first) break;

		case P_NOMATCH:
			WriteOut(MSG_Get("PROGRAM_CONFIG_USAGE"));
			return;

		case P_HELP: case P_HELP2: case P_HELP3: {
			switch(pvars.size()) {
			case 0:
				WriteOut(MSG_Get("PROGRAM_CONFIG_USAGE"));
				return;
			case 1: {
				if (!strcasecmp("sections",pvars[0].c_str())) {
					// list the sections
					WriteOut(MSG_Get("PROGRAM_CONFIG_HLP_SECTLIST"));
					Bitu i = 0;
					while(true) {
						Section* sec = control->GetSection(i++);
						if (!sec) break;
						WriteOut("%s\n",sec->GetName());
					}
					return;
				}
				// if it's a section, leave it as one-param
				Section* sec = control->GetSection(pvars[0].c_str());
				if (!sec) {
					// could be a property
					sec = control->GetSectionFromProperty(pvars[0].c_str());
					if (!sec) {
						WriteOut(MSG_Get("PROGRAM_CONFIG_PROPERTY_ERROR"));
						return;
					}
					pvars.insert(pvars.begin(),std::string(sec->GetName()));
				}
				break;
			}
			case 2: {
				// sanity check
				Section* sec = control->GetSection(pvars[0].c_str());
				Section* sec2 = control->GetSectionFromProperty(pvars[1].c_str());
				if (sec != sec2) {
					WriteOut(MSG_Get("PROGRAM_CONFIG_PROPERTY_ERROR"));
				}
				break;
			}
			default:
				WriteOut(MSG_Get("PROGRAM_CONFIG_USAGE"));
				return;
			}	
			// if we have one value in pvars, it's a section
			// two values are section + property
			Section* sec = control->GetSection(pvars[0].c_str());
			if (sec==NULL) {
				WriteOut(MSG_Get("PROGRAM_CONFIG_PROPERTY_ERROR"));
				return;
			}
			Section_prop* psec = dynamic_cast <Section_prop*>(sec);
			if (psec==NULL) {
				// failed; maybe it's the autoexec section?
				Section_line* pline = dynamic_cast <Section_line*>(sec);
				if (pline==NULL) E_Exit("Section dynamic cast failed.");

				WriteOut(MSG_Get("PROGRAM_CONFIG_HLP_LINEHLP"),
					pline->GetName(),
					// this is 'unclean' but the autoexec section has no help associated
					MSG_Get("AUTOEXEC_CONFIGFILE_HELP"),
					pline->data.c_str() );
				return;
			} 
			if (pvars.size()==1) {
				size_t i = 0;
				WriteOut(MSG_Get("PROGRAM_CONFIG_HLP_SECTHLP"),pvars[0].c_str());
				while(true) {
					// list the properties
					Property* p = psec->Get_prop(i++);
					if (p==NULL) break;
					WriteOut("%s\n", p->propname.c_str());
				}
			} else {
				// find the property by it's name
				size_t i = 0;
				while (true) {
					Property *p = psec->Get_prop(i++);
					if (p==NULL) break;
					if (!strcasecmp(p->propname.c_str(),pvars[1].c_str())) {
						// found it; make the list of possible values
						std::string propvalues;
						std::vector<Value> pv = p->GetValues();
						
						if (p->Get_type()==Value::V_BOOL) {
							// possible values for boolean are true, false
							propvalues += "true, false";
						} else if (p->Get_type()==Value::V_INT) {
							// print min, max for integer values if used
							Prop_int* pint = dynamic_cast <Prop_int*>(p);
							if (pint==NULL) E_Exit("Int property dynamic cast failed.");
							if (pint->getMin() != pint->getMax()) {
								std::ostringstream oss;
								oss << pint->getMin();
								oss << "..";
								oss << pint->getMax();
								propvalues += oss.str();
							}
						}
						for(Bitu k = 0; k < pv.size(); k++) {
							if (pv[k].ToString() =="%u")
								propvalues += MSG_Get("PROGRAM_CONFIG_HLP_POSINT");
							else propvalues += pv[k].ToString();
							if ((k+1) < pv.size()) propvalues += ", ";
						}

						WriteOut(MSG_Get("PROGRAM_CONFIG_HLP_PROPHLP"),
							p->propname.c_str(),
							sec->GetName(),
							p->Get_help(),propvalues.c_str(),
							p->Get_Default_Value().ToString().c_str(),
							p->GetValue().ToString().c_str());
						// print 'changability'
						if (p->getChange()==Property::Changeable::OnlyAtStart) {
							WriteOut(MSG_Get("PROGRAM_CONFIG_HLP_NOCHANGE"));
						}
						return;
					}
				}
				break;
			}
			return;
		}
		case P_AUTOEXEC_CLEAR: {
			Section_line* sec = dynamic_cast <Section_line*>
				(control->GetSection(std::string("autoexec")));
			sec->data.clear();
			break;
		}
		case P_AUTOEXEC_ADD: {
			if (pvars.size() == 0) {
				WriteOut(MSG_Get("PROGRAM_CONFIG_MISSINGPARAM"));
				return;
			}
			Section_line* sec = dynamic_cast <Section_line*>
				(control->GetSection(std::string("autoexec")));

			for(Bitu i = 0; i < pvars.size(); i++) sec->HandleInputline(pvars[i]);
			break;
		}
		case P_AUTOEXEC_TYPE: {
			Section_line* sec = dynamic_cast <Section_line*>
				(control->GetSection(std::string("autoexec")));
			WriteOut("\n%s",sec->data.c_str());
			break;
		}
		case P_GETPROP: {
			// "section property"
			// "property"
			// "section"
			// "section" "property"
			if (pvars.size()==0) {
				WriteOut(MSG_Get("PROGRAM_CONFIG_GET_SYNTAX"));
				return;
			}
			std::string::size_type spcpos = pvars[0].find_first_of(' ');
			// split on the ' '
			if (spcpos != std::string::npos) {
				pvars.insert(++pvars.begin(),pvars[0].substr(spcpos+1));
				pvars[0].erase(spcpos);
			}
			switch(pvars.size()) {
			case 1: {
				// property/section only
				// is it a section?
				Section* sec = control->GetSection(pvars[0].c_str());
				if (sec) {
					// list properties in section
					Bitu i = 0;
					Section_prop* psec = dynamic_cast <Section_prop*>(sec);
					if (psec==NULL) {
						// autoexec section
						Section_line* pline = dynamic_cast <Section_line*>(sec);
						if (pline==NULL) E_Exit("Section dynamic cast failed.");

						WriteOut("%s",pline->data.c_str());
						break;
					}
					while(true) {
						// list the properties
						Property* p = psec->Get_prop(i++);
						if (p==NULL) break;
						WriteOut("%s=%s\n", p->propname.c_str(),
							p->GetValue().ToString().c_str());
					}
				} else {
					// no: maybe it's a property?
					sec = control->GetSectionFromProperty(pvars[0].c_str());
					if (!sec) {
						WriteOut(MSG_Get("PROGRAM_CONFIG_PROPERTY_ERROR"));
						return;
					}
					// it's a property name
					std::string val = sec->GetPropValue(pvars[0].c_str());
					WriteOut("%s",val.c_str());
				}
				break;
			}
			case 2: {
				// section + property
				Section* sec = control->GetSection(pvars[0].c_str());
				if (!sec) {
					WriteOut(MSG_Get("PROGRAM_CONFIG_SECTION_ERROR"));
					return;
				}
				std::string val = sec->GetPropValue(pvars[1].c_str());
				if (val == NO_SUCH_PROPERTY) {
					WriteOut(MSG_Get("PROGRAM_CONFIG_NO_PROPERTY"),
						pvars[1].c_str(),pvars[0].c_str());   
					return;
				}
				WriteOut("%s",val.c_str());
				break;
			}
			default:
				WriteOut(MSG_Get("PROGRAM_CONFIG_GET_SYNTAX"));
				return;
			}
			return;
		}
		case P_SETPROP:	{
			// Code for the configuration changes
			// Official format: config -set "section property=value"
			// Accepted: with or without -set, 
			// "section property value"
			// "section property=value"
			// "property" "value"
			// "section" "property=value"
			// "section" "property=value" "value" "value" ...
			// "section" "property" "value" "value" ...
			// "section property" "value" "value" ...
			// "property" "value" "value" ...
			// "property=value" "value" "value" ...

			if (pvars.size()==0) {
				WriteOut(MSG_Get("PROGRAM_CONFIG_SET_SYNTAX"));
				return;
			}

			// add rest of command
			std::string rest;
			if (cmd->GetStringRemain(rest)) pvars.push_back(rest);

			// attempt to split off the first word
			std::string::size_type spcpos = pvars[0].find_first_of(' ');
			std::string::size_type equpos = pvars[0].find_first_of('=');

			if ((equpos != std::string::npos) && 
				((spcpos == std::string::npos) || (equpos < spcpos))) {
				// If we have a '=' possibly before a ' ' split on the =
				pvars.insert(++pvars.begin(),pvars[0].substr(equpos+1));
				pvars[0].erase(equpos);
				// As we had a = the first thing must be a property now
				Section* sec=control->GetSectionFromProperty(pvars[0].c_str());
				if (sec) pvars.insert(pvars.begin(),std::string(sec->GetName()));
				else {
					WriteOut(MSG_Get("PROGRAM_CONFIG_PROPERTY_ERROR"));
					return;
				}
				// order in the vector should be ok now
			} else {
				if ((spcpos != std::string::npos) &&
					((equpos == std::string::npos) || (spcpos < equpos))) {
					// ' ' before a possible '=', split on the ' '
					pvars.insert(++pvars.begin(),pvars[0].substr(spcpos+1));
					pvars[0].erase(spcpos);
				}
				// check if the first parameter is a section or property
				Section* sec = control->GetSection(pvars[0].c_str());
				if (!sec) {
					// not a section: little duplicate from above
					Section* sec=control->GetSectionFromProperty(pvars[0].c_str());
					if (sec) pvars.insert(pvars.begin(),std::string(sec->GetName()));
					else {
						WriteOut(MSG_Get("PROGRAM_CONFIG_PROPERTY_ERROR"));
						return;
					}
				} else {
					// first of pvars is most likely a section, but could still be gus
					// have a look at the second parameter
					if (pvars.size() < 2) {
						WriteOut(MSG_Get("PROGRAM_CONFIG_SET_SYNTAX"));
						return;
					}
					std::string::size_type spcpos2 = pvars[1].find_first_of(' ');
					std::string::size_type equpos2 = pvars[1].find_first_of('=');
					if ((equpos2 != std::string::npos) && 
						((spcpos2 == std::string::npos) || (equpos2 < spcpos2))) {
						// split on the =
						pvars.insert(pvars.begin()+2,pvars[1].substr(equpos2+1));
						pvars[1].erase(equpos2);
					} else if ((spcpos2 != std::string::npos) &&
						((equpos2 == std::string::npos) || (spcpos2 < equpos2))) {
						// split on the ' '
						pvars.insert(pvars.begin()+2,pvars[1].substr(spcpos2+1));
						pvars[1].erase(spcpos2);
					}
					// is this a property?
					Section* sec2 = control->GetSectionFromProperty(pvars[1].c_str());
					if (!sec2) {
						// not a property, 
						Section* sec3 = control->GetSectionFromProperty(pvars[0].c_str());
						if (sec3) {
							// section and property name are identical
							pvars.insert(pvars.begin(),pvars[0]);
						} // else has been checked above already
					}
				}
			}
			if(pvars.size() < 3) {
				WriteOut(MSG_Get("PROGRAM_CONFIG_SET_SYNTAX"));
				return;
			}
			// check if the property actually exists in the section
			Section* sec2 = control->GetSectionFromProperty(pvars[1].c_str());
			if (!sec2) {
				WriteOut(MSG_Get("PROGRAM_CONFIG_NO_PROPERTY"),
					pvars[1].c_str(),pvars[0].c_str());
				return;
			}
			// Input has been parsed (pvar[0]=section, [1]=property, [2]=value)
			// now execute
			Section* tsec = control->GetSection(pvars[0]);
			std::string value;
			value += pvars[2];
			for(Bitu i = 3; i < pvars.size(); i++) value += (std::string(" ") + pvars[i]);
			std::string inputline = pvars[1] + "=" + value;
			
			tsec->ExecuteDestroy(false);
			bool change_success = tsec->HandleInputline(inputline.c_str());
			if (!change_success) WriteOut(MSG_Get("PROGRAM_CONFIG_VALUE_ERROR"),
				value.c_str(),pvars[1].c_str());
			tsec->ExecuteInit(false);
			return;
		}
		case P_WRITELANG: case P_WRITELANG2:
			// In secure mode don't allow a new languagefile to be created
			// Who knows which kind of file we would overwrite.
			if (securemode_check()) return;
			if (pvars.size() < 1) {
				WriteOut(MSG_Get("PROGRAM_CONFIG_MISSINGPARAM"));
				return;
			}
			if (!MSG_Write(pvars[0].c_str())) {
				WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),pvars[0].c_str());
				return;
			}
			break;

		case P_SECURE:
			// Code for switching to secure mode
			control->SwitchToSecureMode();
			WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_ON"));
			return;

		default:
			E_Exit("bug");
			break;
		}
		first = false;
	}
	return;
}
Exemple #4
0
int updatebin(int idx, char *par, int secs)
{
  if (!par || !par[0]) {
    logidx(idx, "Not enough parameters.");
    return 1;
  }

  size_t path_siz = strlen(binname) + strlen(par) + 2;
  char *path = (char *) my_calloc(1, path_siz);
  char *newbin = NULL, buf[DIRMAX] = "";
  const char* argv[5];
  int i;

  strlcpy(path, binname, path_siz);
  newbin = strrchr(path, '/');
  if (!newbin) {
    free(path);
    logidx(idx, STR("Don't know current binary name"));
    return 1;
  }
  newbin++;
  if (strchr(par, '/')) {
    *newbin = 0;
    logidx(idx, STR("New binary must be in %s and name must be specified without path information"), path);
    free(path);
    return 1;
  }
  strcpy(newbin, par);
  if (!strcmp(path, binname)) {
    free(path);
    logidx(idx, STR("Can't update with the current binary"));
    return 1;
  }
  if (!can_stat(path)) {
    logidx(idx, STR("%s can't be accessed"), path);
    free(path);
    return 1;
  }
  if (fixmod(path)) {
    logidx(idx, STR("Can't set mode 0600 on %s"), path);
    free(path);
    return 1;
  }

  /* Check if the new binary is compatible */
  int initialized_code = check_bin_initialized(path);
  if (initialized_code == 2) {
    logidx(idx, STR("New binary is corrupted or the wrong architecture/operating system."));
    free(path);
    return 1;
  } else if (initialized_code == 1 && !check_bin_compat(path)) {
    logidx(idx, STR("New binary must be initialized as pack structure has been changed in new version."));
    free(path);
    return 1;
  }


  /* make a backup just in case. */

  simple_snprintf(buf, sizeof(buf), STR("%s/.bin.old"), conf.datadir);
  copyfile(binname, buf);

  write_settings(path, -1, 0, initialized_code ? 0 : 1);	/* re-write the binary with our packdata */

  Tempfile *conffile = new Tempfile("conf");

  if (writeconf(NULL, conffile->fd, CONF_ENC)) {
    logidx(idx, STR("Failed to write temporary config file for update."));
    delete conffile;
    return 1;
  }

  /* The binary should return '2' when ran with -2, if not it's probably corrupt. */
  putlog(LOG_DEBUG, "*", STR("Running for update binary test: %s -2"), path);
  argv[0] = path;
  argv[1] = "-2";
  argv[2] = 0;
  i = simple_exec(argv);
  if (i == -1 || WEXITSTATUS(i) != 2) {
    logidx(idx, STR("Couldn't restart new binary (error %d)"), i);
    delete conffile;
    return i;
  }

  /* now to send our config to the new binary */
  putlog(LOG_DEBUG, "*", STR("Running for update conf: %s -4 %s"), path, conffile->file);
  argv[0] = path;
  argv[1] = "-4";
  argv[2] = conffile->file;
  argv[3] = 0;
  i = simple_exec(argv);
  delete conffile;
  if (i == -1 || WEXITSTATUS(i) != 6) { /* 6 for successfull config read/write */
    logidx(idx, STR("Couldn't pass config to new binary (error %d)"), i);
    return i;
  }

  if (movefile(path, binname)) {
    logidx(idx, STR("Can't rename %s to %s"), path, binname);
    free(path);
    return 1;
  }

  if (updating == UPDATE_EXIT) {	  /* dont restart/kill/spawn bots, just die ! */
    printf(STR("* Moved binary to: %s\n"), binname);
    fatal(STR("Binary updated."), 0);
  }
  if (updating == UPDATE_AUTO) {
    /* Make all other bots do a soft restart */
    conf_checkpids(conf.bots);
    conf_killbot(conf.bots, NULL, NULL, SIGHUP);

    if (conf.bot->pid)
      kill(conf.bot->pid, SIGHUP);
    exit(0);
  }

  if (!conf.bot->hub && secs > 0) {
    /* Make all other bots do a soft restart */
    conf_checkpids(conf.bots);
    conf_killbot(conf.bots, NULL, NULL, SIGHUP);
    
    /* invoked with -u */
    if (updating == UPDATE_AUTO) {
      if (conf.bot->pid)
        kill(conf.bot->pid, SIGHUP);
      exit(0);
    }
    /* this odd statement makes it so specifying 1 sec will restart other bots running
     * and then just restart with no delay */
    updating = UPDATE_AUTO;
    if (secs > 1) {
      egg_timeval_t howlong;
      howlong.sec = secs;
      howlong.usec = 0;
      timer_create_complex(&howlong, STR("restarting for update"), (Function) restart, (void *) (long) idx, 0);
    } else
      restart(idx);

    return 0;
  } else
    restart(idx);	/* no timer */

 /* this should never be reached */
  return 2;
}