diff --git a/core/includes/install.inc b/core/includes/install.inc
index 256c79e..d017773 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -634,8 +634,14 @@ function drupal_install_system() {
 
   $system_path = drupal_get_path('module', 'system');
   require_once DRUPAL_ROOT . '/' . $system_path . '/system.install';
+
+  // Set the schema version to the number of the last update provided by the
+  // module, or the minimum core schema version.
+  $system_version = \Drupal::CORE_MINIMUM_SCHEMA_VERSION;
   $system_versions = drupal_get_schema_versions('system');
-  $system_version = $system_versions ? max($system_versions) : SCHEMA_INSTALLED;
+  if ($system_versions) {
+    $system_version = max(max($system_versions), $system_version);
+  }
   \Drupal::keyValue('system.schema')->set('system', $system_version);
 
   // System module needs to be enabled and the system/module lists need to be
diff --git a/core/includes/schema.inc b/core/includes/schema.inc
index d0fd30b..40ca702 100644
--- a/core/includes/schema.inc
+++ b/core/includes/schema.inc
@@ -8,6 +8,7 @@
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Database\Database;
 use Drupal\Core\Utility\SchemaCache;
+use Drupal\Core\Extension\ExtensionSchemaVersionException;
 
 /**
  * @addtogroup schemaapi
@@ -20,11 +21,6 @@
 const SCHEMA_UNINSTALLED = -1;
 
 /**
- * Indicates that a module has been installed.
- */
-const SCHEMA_INSTALLED = 0;
-
-/**
  * Gets the schema definition of a table, or the whole database schema.
  *
  * The returned schema will include any modifications made by any
@@ -143,7 +139,17 @@ function drupal_get_schema_versions($module) {
       }
     }
     // Ensure that updates are applied in numerical order.
-    foreach ($updates as &$module_updates) {
+    foreach ($updates as $module_name => &$module_updates) {
+      // No module is allowed to define a schema update of exactly
+      // \Drupal::CORE_MINIMUM_SCHEMA_VERSION because this is reserved for the
+      // minimum installed version.
+      if (in_array(\Drupal::CORE_MINIMUM_SCHEMA_VERSION, $module_updates)) {
+        throw new ExtensionSchemaVersionException(format_string("%module_name's hook_update_N() implementations must use N greater than @version.", array(
+          '%module_name' => $module_name,
+          '@version' => \Drupal::CORE_MINIMUM_SCHEMA_VERSION,
+        )));
+      }
+
       sort($module_updates, SORT_NUMERIC);
     }
   }
diff --git a/core/includes/update.inc b/core/includes/update.inc
index b17624f..30bea0f 100644
--- a/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -19,16 +19,6 @@
 use Symfony\Component\HttpFoundation\Request;
 
 /**
- * Minimum schema version of Drupal 7 required for upgrade to Drupal 8.
- *
- * Upgrades from Drupal 7 to Drupal 8 require that Drupal 7 be running
- * the most recent version, or the upgrade could fail. We can't easily
- * check the Drupal 7 version once the update process has begun, so instead
- * we check the schema version of system.module.
- */
-const REQUIRED_D7_SCHEMA_VERSION = '7069';
-
-/**
  * Disables any extensions that are incompatible with the current core version.
  */
 function update_fix_compatibility() {
@@ -148,9 +138,8 @@ function update_prepare_d8_bootstrap() {
   // below.
   require_once __DIR__ . '/module.inc';
 
-  // If the site has not updated to Drupal 8 yet, check to make sure that it is
-  // running an up-to-date version of Drupal 7 before proceeding. Note this has
-  // to happen AFTER the database bootstraps because of
+  // Ensure that the site is running Drupal 8 before proceeding. Not that this
+  // has to happen AFTER the database bootstraps because of
   // drupal_get_installed_schema_version().
   try {
     $system_schema = drupal_get_installed_schema_version('system');
@@ -158,282 +147,16 @@ function update_prepare_d8_bootstrap() {
   catch (\Exception $e) {
     $system_schema = db_query('SELECT schema_version FROM {system} WHERE name = :system', array(':system' => 'system'))->fetchField();
   }
-  if ($system_schema < 8000) {
-    $has_required_schema = $system_schema >= REQUIRED_D7_SCHEMA_VERSION;
+  if ($system_schema < \Drupal::CORE_MINIMUM_SCHEMA_VERSION) {
     $requirements = array(
       'drupal 7 version' => array(
         'title' => 'Drupal 7 version',
-        'value' => $has_required_schema ? 'You are running a current version of Drupal 7.' : 'You are not running a current version of Drupal 7',
-        'severity' => $has_required_schema ? NULL : REQUIREMENT_ERROR,
-        'description' => $has_required_schema ? '' : 'Please update your Drupal 7 installation to the most recent version before attempting to upgrade to Drupal 8',
+        'value' => 'Your site database is from a Drupal 7 or earlier site.',
+        'severity' => REQUIREMENT_ERROR,
+        'description' => 'Please migrate your Drupal 7 installation to a Drupal 8 installation using the Migrate module. Updating directly from Drupal 7 to Drupal 8 is not supported.',
       ),
     );
     update_extra_requirements($requirements);
-
-    // @todo update.php stages seem to be completely screwed up; the initial
-    //   requirements check is not supposed to change the system. All of the
-    //   following code seems to have been mistakenly/unknowingly added here and
-    //   does not belong into update_prepare_d8_bootstrap().
-    if ($has_required_schema) {
-      if (!db_table_exists('key_value')) {
-        $specs = array(
-          'description' => 'Generic key-value storage table. See the state system for an example.',
-          'fields' => array(
-            'collection' => array(
-              'description' => 'A named collection of key and value pairs.',
-              'type' => 'varchar',
-              'length' => 128,
-              'not null' => TRUE,
-              'default' => '',
-            ),
-            'name' => array(
-              'description' => 'The key of the key-value pair. As KEY is a SQL reserved keyword, name was chosen instead.',
-              'type' => 'varchar',
-              'length' => 128,
-              'not null' => TRUE,
-              'default' => '',
-            ),
-            'value' => array(
-              'description' => 'The value.',
-              'type' => 'blob',
-              'not null' => TRUE,
-              'size' => 'big',
-              'translatable' => TRUE,
-            ),
-          ),
-          'primary key' => array('collection', 'name'),
-        );
-        db_create_table('key_value', $specs);
-      }
-      if (!db_table_exists('cache_tags')) {
-        $table = array(
-          'description' => 'Cache table for tracking cache tags related to the cache bin.',
-          'fields' => array(
-            'tag' => array(
-              'description' => 'Namespace-prefixed tag string.',
-              'type' => 'varchar',
-              'length' => 255,
-              'not null' => TRUE,
-              'default' => '',
-            ),
-            'invalidations' => array(
-              'description' => 'Number incremented when the tag is invalidated.',
-              'type' => 'int',
-              'not null' => TRUE,
-              'default' => 0,
-            ),
-            'deletions' => array(
-              'description' => 'Number incremented when the tag is deleted.',
-              'type' => 'int',
-              'not null' => TRUE,
-              'default' => 0,
-            ),
-          ),
-          'primary key' => array('tag'),
-        );
-        db_create_table('cache_tags', $table);
-      }
-      if (!db_table_exists('cache_config')) {
-        $spec = array(
-          'description' =>  'Cache table for configuration data.',
-          'fields' => array(
-            'cid' => array(
-              'description' => 'Primary Key: Unique cache ID.',
-              'type' => 'varchar',
-              'length' => 255,
-              'not null' => TRUE,
-              'default' => '',
-            ),
-            'data' => array(
-              'description' => 'A collection of data to cache.',
-              'type' => 'blob',
-              'not null' => FALSE,
-              'size' => 'big',
-            ),
-            'expire' => array(
-              'description' => 'A Unix timestamp indicating when the cache entry should expire, or 0 for never.',
-              'type' => 'int',
-              'not null' => TRUE,
-              'default' => 0,
-            ),
-            'created' => array(
-              'description' => 'A Unix timestamp indicating when the cache entry was created.',
-              'type' => 'int',
-              'not null' => TRUE,
-              'default' => 0,
-            ),
-            'serialized' => array(
-              'description' => 'A flag to indicate whether content is serialized (1) or not (0).',
-              'type' => 'int',
-              'size' => 'small',
-              'not null' => TRUE,
-              'default' => 0,
-            ),
-            'tags' => array(
-              'description' => 'Space-separated list of cache tags for this entry.',
-              'type' => 'text',
-              'size' => 'big',
-              'not null' => FALSE,
-            ),
-            'checksum_invalidations' => array(
-              'description' => 'The tag invalidation sum when this entry was saved.',
-              'type' => 'int',
-              'not null' => TRUE,
-              'default' => 0,
-            ),
-            'checksum_deletions' => array(
-              'description' => 'The tag deletion sum when this entry was saved.',
-              'type' => 'int',
-              'not null' => TRUE,
-              'default' => 0,
-            ),
-          ),
-          'indexes' => array(
-            'expire' => array('expire'),
-          ),
-          'primary key' => array('cid'),
-        );
-        db_create_table('cache_config', $spec);
-      }
-
-      require_once DRUPAL_ROOT . '/core/modules/system/system.install';
-      $tables = array(
-        'cache',
-        'cache_bootstrap',
-        'cache_block',
-        'cache_field',
-        'cache_filter',
-        'cache_form',
-        'cache_image',
-        'cache_menu',
-        'cache_page',
-        'cache_path',
-        'cache_update',
-      );
-
-      foreach ($tables as $table) {
-        update_add_cache_columns($table);
-      }
-
-      // Bootstrap variables so we can update theme while preparing the update
-      // process.
-      drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES);
-
-      // Update the 'language_default' system variable, if configured.
-      // Required to run before drupal_install_config_directories(), since that
-      // triggers a call into system_stream_wrappers(), which calls t(), which
-      // calls into language_default().
-      $language_default = update_variable_get('language_default');
-      if (!empty($language_default) && (isset($language_default->id) || isset($language_default->language))) {
-        if (!isset($language_default->id)) {
-          $language_default->id = $language_default->language;
-        }
-        unset($language_default->language);
-        // In D8, the 'language_default' is not anymore an object, but an array,
-        // so make sure that the new value that is saved into this variable is an
-        // array.
-        update_variable_set('language_default', (array) $language_default);
-      }
-
-      $module_config = \Drupal::config('system.module');
-      $theme_config = \Drupal::config('system.theme');
-      $disabled_themes = \Drupal::config('system.theme.disabled');
-      $schema_store = \Drupal::keyValue('system.schema');
-
-      // Load system.module, because update_prepare_d8_bootstrap() is called in
-      // the initial minimal update.php bootstrap that performs the core
-      // requirements check.
-      require_once DRUPAL_ROOT . '/core/modules/system/system.module';
-
-      // Make sure that the bootstrap cache is cleared as that might contain
-      // incompatible data structures.
-      cache('bootstrap')->deleteAll();
-
-      // Retrieve all installed extensions from the {system} table.
-      // Uninstalled extensions are ignored and not converted.
-      $result = db_query('SELECT name, status, weight, schema_version, type FROM {system} WHERE type = :theme OR (type = :module AND schema_version <> :schema_uninstalled)', array(
-        ':theme' => 'theme',
-        ':module' => 'module',
-        ':schema_uninstalled' => SCHEMA_UNINSTALLED,
-      ));
-
-      $module_data = _system_rebuild_module_data();
-
-      // Migrate each extension into configuration, varying by the extension's
-      // status, and record its schema version.
-      foreach ($result as $record) {
-        // Before migrating any extension into configuration, make sure the
-        // extensions name length is not higher than the limit.
-        if (drupal_strlen($record->name) > 50) {
-          $requirements['module name too long ' . $record->name] = array(
-            'title' => 'Module name too long',
-            'value' => format_string('@name is @count characters long.', array('@name' => $record->name, '@count' => drupal_strlen($record->name))),
-            'description' => 'Module names longer than 50 characters are <a href="https://drupal.org/node/2014073">no longer supported</a>.',
-            'severity' => REQUIREMENT_ERROR,
-          );
-          update_extra_requirements($requirements);
-        }
-
-        if ($record->type == 'module') {
-          if ($record->status && isset($module_data[$record->name])) {
-            $module_config->set('enabled.' . $record->name, $record->weight);
-          }
-        }
-        elseif ($record->type == 'theme') {
-          if ($record->status) {
-            $theme_config->set('enabled.' . $record->name, 0);
-          }
-          else {
-            $disabled_themes->set($record->name, 0);
-          }
-        }
-        $schema_store->set($record->name, $record->schema_version);
-      }
-      $sorted_modules = module_config_sort($module_config->get('enabled'));
-      $module_config->set('enabled', $sorted_modules)->save();
-      $sorted_with_filenames = array();
-      foreach (array_keys($sorted_modules) as $m) {
-        $sorted_with_filenames[$m] = drupal_get_filename('module', $m);
-      }
-      \Drupal::moduleHandler()->setModuleList($sorted_with_filenames);
-      $theme_config->save();
-      $disabled_themes->save();
-
-      // Migrate the private key to state. This is used to create the token for
-      // the upgrade batch so needs to be be done before the upgrade has begun.
-      update_variables_to_state(array(
-        'drupal_private_key' => 'system.private_key',
-      ));
-
-      // Update the dynamic include paths that might be used before running the
-      // proper update functions.
-      update_prepare_stored_includes();
-      // Update the environment for the language bootstrap if needed.
-      update_prepare_d8_language();
-      // Rebuild kernel after new language fields are added in the database
-      // because the translation service depends on them being there.
-      \Drupal::service('kernel')->updateModules($sorted_with_filenames, $sorted_with_filenames);
-
-      // Change language column to langcode in url_alias.
-      if (db_table_exists('url_alias') && db_field_exists('url_alias', 'language')) {
-        db_drop_index('url_alias', 'alias_language_pid');
-        db_drop_index('url_alias', 'source_language_pid');
-        $langcode_spec = array(
-          'description' => "The language code this alias is for; if 'und', the alias will be used for unknown languages. Each Drupal path can have an alias for each supported language.",
-          'type' => 'varchar',
-          'length' => 12,
-          'not null' => TRUE,
-          'default' => '',
-        );
-        $langcode_indexes = array('indexes' =>
-          array(
-            'alias_langcode_pid' => array('alias', 'langcode', 'pid'),
-            'source_langcode_pid' => array('source', 'langcode', 'pid'),
-          ),
-        );
-        db_change_field('url_alias', 'language', 'langcode', $langcode_spec, $langcode_indexes);
-      }
-    }
   }
   // Moves install_profile from variable to settings. You can't do that in
   // system.install because _system_rebuild_module_data() needs the profile
@@ -465,275 +188,6 @@ function update_prepare_d8_bootstrap() {
 }
 
 /**
- * Fixes stored include paths to match the "/core" migration.
- */
-function update_prepare_stored_includes() {
-  // Retrieve the currently stored language types. Default to the hardcoded D7
-  // values.
-  $default_language_types = array('language' => TRUE, 'language_content' => FALSE, 'language_url' => FALSE);
-  $language_types = array_keys(update_variable_get('language_types', $default_language_types));
-
-  // Update language negotiation settings.
-  foreach ($language_types as $language_type) {
-    $negotiation = update_variable_get("language_negotiation_$language_type", array());
-    foreach ($negotiation as &$method) {
-      if (isset($method['file']) && $method['file'] == 'includes/locale.inc') {
-        $method['file'] = 'core/modules/language/language.negotiation.inc';
-      }
-    }
-    update_variable_set("language_negotiation_$language_type", $negotiation);
-  }
-}
-
-/**
- * Prepares Drupal 8 language changes for the bootstrap if needed.
- */
-function update_prepare_d8_language() {
-  if (db_table_exists('languages')) {
-    \Drupal::moduleHandler()->install(array('language'));
-
-    $languages = db_select('languages', 'l')
-      ->fields('l')
-      ->execute();
-    $plurals = array();
-    $javascript = array();
-    $prefixes = array();
-    $domains = array();
-    foreach ($languages as $language) {
-      $plurals[$language->language] = array(
-        'plurals' => $language->plurals,
-        'formula' => $language->formula,
-      );
-      $javascript[$language->language] = $language->javascript;
-      $prefixes[$language->language] = $language->prefix;
-      $domains[$language->language] = $language->domain;
-    }
-    \Drupal::state()->set('locale.translation.plurals', $plurals);
-    \Drupal::state()->set('locale.translation.javascript', $javascript);
-    \Drupal::config('language.negotiation')
-      ->set('url.prefixes', $prefixes)
-      ->set('url.domains', $domains)
-      ->save();
-
-    // Drop now unneeded columns.
-    db_drop_field('languages', 'plurals');
-    db_drop_field('languages', 'formula');
-    db_drop_field('languages', 'javascript');
-    db_drop_field('languages', 'prefix');
-    db_drop_field('languages', 'domain');
-    db_drop_field('languages', 'native');
-    db_drop_field('languages', 'enabled');
-
-    // Update language count.
-    \Drupal::state()->set('language_count', db_query('SELECT COUNT(language) FROM {languages}')->fetchField());
-
-    // Rename the languages table to language.
-    db_rename_table('languages', 'language');
-
-    // Rename language column to langcode and set it again as the primary key.
-    if (db_field_exists('language', 'language')) {
-      db_drop_primary_key('language');
-      $langcode_spec = array(
-        'type' => 'varchar',
-        'length' => 12,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => "Language code, e.g. 'de' or 'en-US'.",
-      );
-      db_change_field('language', 'language', 'langcode', $langcode_spec, array('primary key' => array('langcode')));
-    }
-
-    // Adds the locked column and saves the special languages.
-    if (!db_field_exists('language', 'locked')) {
-      $locked_spec = array(
-        'type' => 'int',
-        'size' => 'tiny',
-        'not null' => TRUE,
-        'default' => 0,
-        'description' => 'A boolean indicating whether the administrator can edit or delete the language.',
-      );
-      db_add_field('language', 'locked', $locked_spec);
-
-      $max_language_weight = db_query('SELECT MAX(weight) FROM {language}')->fetchField();
-      $languages = language_default_locked_languages($max_language_weight);
-      foreach ($languages as $language) {
-        db_insert('language')
-          ->fields(array(
-            'langcode' => $language->id,
-            'name' => $language->name,
-            'weight' => $language->weight,
-            // These languages are locked, default to enabled.
-            'locked' => 1,
-          ))
-          ->execute();
-      }
-    }
-
-    // Update the 'language_default' system variable with the langcode change.
-    $language_default = update_variable_get('language_default');
-    if (!empty($language_default)) {
-      if (isset($language_default->language)) {
-        $language_default->id = $language_default->language;
-        unset($language_default->language);
-      }
-      unset($language_default->enabled);
-      // In D8, the 'language_default' is not anymore an object, but an array,
-      // so make sure that the new value that is saved into this variable is an
-      // array.
-      $language_default = (array) $language_default;
-      $language_default['langcode'] = 'en';
-      update_variable_set('language_default', $language_default);
-    }
-
-    // Convert languages to config entities.
-    $result = db_query('SELECT * FROM {language}');
-    $uuid = \Drupal::service('uuid');
-    foreach ($result as $language) {
-      \Drupal::config('language.entity.' . $language->langcode)
-        ->set('id', $language->langcode)
-        ->set('uuid', $uuid->generate())
-        ->set('label', $language->name)
-        ->set('direction', $language->direction)
-        ->set('weight', $language->weight)
-        ->set('locked', $language->locked)
-        ->set('langcode', 'en')
-        ->save();
-    }
-
-    // Add column to track customized string status to locales_target.
-    // When updating in a non-English language, the locale translation system is
-    // triggered, which attempts to query string translations already.
-    if (db_table_exists('locales_target') && !db_field_exists('locales_target', 'customized')) {
-      $spec = array(
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0, // LOCALE_NOT_CUSTOMIZED
-        'description' => 'Boolean indicating whether the translation is custom to this site.',
-      );
-      db_add_field('locales_target', 'customized', $spec);
-    }
-    // Add locales_location table to track string locations.
-    // When updating in a non-English language, this table is used for
-    // refreshing JavaScript translations.
-    if (db_table_exists('locales_source') && !db_table_exists('locales_location')) {
-      $table = array(
-        'description' => 'Location information for source strings.',
-        'fields' => array(
-          'lid' => array(
-            'type' => 'serial',
-            'not null' => TRUE,
-            'description' => 'Unique identifier of this location.',
-          ),
-          'sid' => array(
-            'type' => 'int',
-            'not null' => TRUE,
-            'description' => 'Unique identifier of this string.',
-          ),
-          'type' => array(
-            'type' => 'varchar',
-            'length' => 50,
-            'not null' => TRUE,
-            'default' => '',
-            'description' => 'The location type (file, config, path, etc).',
-          ),
-          'name' => array(
-            'type' => 'varchar',
-            'length' => 255,
-            'not null' => TRUE,
-            'default' => '',
-            'description' => 'Type dependent location information (file name, path, etc).',
-          ),
-          'version' => array(
-            'type' => 'varchar',
-            'length' => 20,
-            'not null' => TRUE,
-            'default' => 'none',
-            'description' => 'Version of Drupal where the location was found.',
-          ),
-        ),
-        'primary key' => array('lid'),
-        'foreign keys' => array(
-          'locales_source' => array(
-            'table' => 'locales_source',
-            'columns' => array('sid' => 'lid'),
-          ),
-        ),
-        'indexes' => array(
-          'string_id' => array('sid'),
-          'string_type' => array('sid', 'type'),
-        ),
-      );
-
-      db_create_table('locales_location', $table);
-    }
-  }
-}
-
-/**
- * Performs Drupal 7.x to 8.x required update.php updates.
- *
- * This function runs when update.php is run the first time for 8.x,
- * even before updates are selected or performed. It is important
- * that if updates are not ultimately performed that no changes are
- * made which make it impossible to continue using the prior version.
- */
-function update_fix_d8_requirements() {
-  if (drupal_get_installed_schema_version('system') < 8000 && !update_variable_get('update_d8_requirements', FALSE)) {
-
-    // Make sure that file.module is enabled as it is required for the user
-    // picture upgrade path.
-    \Drupal::moduleHandler()->install(array('file'));
-
-    $schema = array(
-      'description' => 'Generic key/value storage table with an expiration.',
-      'fields' => array(
-        'collection' => array(
-          'description' => 'A named collection of key and value pairs.',
-          'type' => 'varchar',
-          'length' => 128,
-          'not null' => TRUE,
-          'default' => '',
-        ),
-        'name' => array(
-          // KEY is an SQL reserved word, so use 'name' as the key's field name.
-          'description' => 'The key of the key/value pair.',
-          'type' => 'varchar',
-          'length' => 128,
-          'not null' => TRUE,
-          'default' => '',
-        ),
-        'value' => array(
-          'description' => 'The value of the key/value pair.',
-          'type' => 'blob',
-          'not null' => TRUE,
-          'size' => 'big',
-        ),
-        'expire' => array(
-          'description' => 'The time since Unix epoch in seconds when this item expires. Defaults to the maximum possible time.',
-          'type' => 'int',
-          'not null' => TRUE,
-          'default' => 2147483647,
-        ),
-      ),
-      'primary key' => array('collection', 'name'),
-      'indexes' => array(
-        'all' => array('name', 'collection', 'expire'),
-      ),
-    );
-    db_create_table('key_value_expire', $schema);
-
-    // Views module is required to convert all previously existing listings into
-    // views configurations.
-    // Like any other module APIs and services, Views' services are not available
-    // in update.php. Existing listings are migrated into configuration, using
-    // the limited standard tools of raw database queries and \Drupal::config().
-    \Drupal::moduleHandler()->install(array('views'));
-
-    update_variable_set('update_d8_requirements', TRUE);
-  }
-}
-
-/**
  * Forces a module to a given schema version.
  *
  * This function is rarely necessary.
@@ -984,7 +438,7 @@ function update_get_update_list() {
   $modules = drupal_get_installed_schema_version(NULL, FALSE, TRUE);
   foreach ($modules as $module => $schema_version) {
     // Skip uninstalled and incompatible modules.
-    if ($schema_version == SCHEMA_UNINSTALLED || update_check_incompatibility($module)) {
+    if ($schema_version == SCHEMA_UNINSTALLED || $schema_version < \Drupal::CORE_MINIMUM_SCHEMA_VERSION || update_check_incompatibility($module)) {
       continue;
     }
     // Otherwise, get the list of updates defined by this module.
@@ -1148,10 +602,10 @@ function update_get_update_function_list($starting_updates) {
  * requirement that the first update function needs to run before the second.
  * For example, consider this graph:
  *
- * system_update_8000 ---> system_update_8001 ---> system_update_8002
+ * system_update_8001 ---> system_update_8002 ---> system_update_8003
  *
- * Visually, this indicates that system_update_8000() must run before
- * system_update_8001(), which in turn must run before system_update_8002().
+ * Visually, this indicates that system_update_8001() must run before
+ * system_update_8002(), which in turn must run before system_update_8003().
  *
  * The function takes into account standard dependencies within each module, as
  * shown above (i.e., the fact that each module's updates must run in numerical
@@ -1304,15 +758,15 @@ function update_retrieve_dependencies() {
               // implementation of hook_update_dependencies() required this
               // ordering:
               //
-              // system_update_8001 ---> user_update_8000
+              // system_update_8002 ---> user_update_8001
               //
               // but another module's implementation of the hook required this
               // one:
               //
-              // system_update_8002 ---> user_update_8000
+              // system_update_8003 ---> user_update_8001
               //
-              // we record the second one, since system_update_8001() is always
-              // guaranteed to run before system_update_8002() anyway (within
+              // we record the second one, since system_update_8002() is always
+              // guaranteed to run before system_update_8003() anyway (within
               // an individual module, updates are always run in numerical
               // order).
               if (!isset($return[$module][$update][$module_dependency]) || $update_dependency > $return[$module][$update][$module_dependency]) {
@@ -1329,207 +783,6 @@ function update_retrieve_dependencies() {
 }
 
 /**
- * Gets the value of a variable from the database during 7.x-8.x upgrades.
- *
- * Use this during the 7.x-8.x upgrade path instead of variable_get().
- *
- * @param string $name
- *   The name of the variable.
- * @param mixed $default
- *   The default value of the variable.
- *
- * @return mixed
- *   The value of the variable in the database unserialized, or NULL if not set.
- *
- * @see update_variable_set()
- * @see update_variable_del()
- * @ingroup config_upgrade
- */
-function update_variable_get($name, $default = NULL) {
-  $result = db_query('SELECT value FROM {variable} WHERE name = :name', array(':name' => $name))->fetchField();
-  if ($result !== FALSE) {
-    return unserialize($result);
-  }
-  return $default;
-}
-
-/**
- * Sets a persistent variable during the 7.x-8.x upgrade path.
- *
- * Use this during the 7.x-8.x upgrade path instead of variable_set().
- *
- * @param string $name
- *   The name of the variable to set.
- * @param mixed $value
- *   The value to set. This can be any PHP data type; these functions take care
- *   of serialization as necessary.
- *
- * @see update_variable_get()
- * @see update_variable_del()
- * @ingroup config_upgrade
- */
-function update_variable_set($name, $value) {
-  db_merge('variable')
-    ->key(array(
-      'name' => $name,
-    ))
-    ->fields(array(
-      'value' => serialize($value),
-    ))
-    ->execute();
-}
-
-/**
- * Delete a variable from the database during the 7.x-8.x upgrade path.
- *
- * Use this during the 7.x-8.x upgrade path instead of variable_del().
- *
- * @param string $name
- *   The name of the variable to delete.
- *
- * @see update_variable_get()
- * @see update_variable_set()
- * @ingroup config_upgrade
- */
-function update_variable_del($name) {
-  db_delete('variable')
-    ->condition('name', $name)
-    ->execute();
-}
-
-/**
- * Updates config with values set on Drupal 7.x.
- *
- * Provides a generalised method to migrate variables from Drupal 7 to
- * Drupal 8's configuration management system.
- *
- * @param string $config_name
- *   The configuration object name to retrieve.
- * @param array $variable_map
- *   An associative array that maps old variables names to new configuration
- *   object keys; e.g.:
- *   @code
- *     array('old_variable' => 'new_config.sub_key')
- *   @endcode
- *   This would migrate the value contained in variable name 'old_variable' into
- *   the data key 'new_config.sub_key' of the configuration object $config_name.
- */
-function update_variables_to_config($config_name, array $variable_map) {
-  // Build the new configuration object.
-  // This potentially loads an existing configuration object, in case another
-  // update function migrated configuration values into $config_name already.
-  $config = \Drupal::config($config_name);
-  $original_data = $config->get();
-
-  // Extract the module namespace/owner from the configuration object name.
-  $module = strtok($config_name, '.');
-
-  // Load and set default configuration values.
-  $file = new FileStorage(drupal_get_path('module', $module) . '/config');
-  if (!$file->exists($config_name)) {
-    throw new ConfigException("Default configuration file $config_name for $module extension not found but is required to exist.");
-  }
-  $default_data = $file->read($config_name);
-
-  // Apply the default values.
-  $config->setData($default_data);
-
-  // Merge any possibly existing original data into default values.
-  // Only relevant when being called repetitively on the same config object.
-  if (!empty($original_data)) {
-    $config->merge($original_data);
-  }
-
-  // Fetch existing variables.
-  $variables = db_query('SELECT name, value FROM {variable} WHERE name IN (:variables)', array(':variables' => array_keys($variable_map)))->fetchAllKeyed();
-
-  // Set configuration values according to the provided variable mapping.
-  foreach ($variable_map as $variable_name => $config_key) {
-    // This function migrates variables regardless of their value, including
-    // NULL values. Any possibly required customizations need to be performed
-    // manually, either via variable_set() before calling this function or via
-    // \Drupal::config() after calling this function.
-    if (isset($variables[$variable_name])) {
-      $value = unserialize($variables[$variable_name]);
-      $config->set($config_key, $value);
-    }
-  }
-
-  // Save the configuration object.
-  $config->save();
-
-  // Delete the migrated variables.
-  db_delete('variable')->condition('name', array_keys($variable_map), 'IN')->execute();
-}
-
-/**
- * Installs a default configuration file into the active store.
- *
- * Provide a generalised method to save a default configuration object for an
- * already enabled module or theme as part of an update from Drupal 7 to Drupal
- * 8's configuration management system.
- *
- * @param string $type
- *   The extension type; e.g., 'module' or 'theme'.
- * @param string $config_name
- *   The configuration object name to retrieve.
- * @param string $name
- *   (optional) The owner of the config. Defaults to NULL, in which case the
- *   name will be derived from the $config_name.
- *
- * @return boolean
- *   True on success, false if config file does not exist.
- */
-function update_install_default_config($type, $config_name, $name = NULL) {
-  // Build the new configuration object.
-  $config = \Drupal::config($config_name);
-
-  // Extract the extension namespace/owner from the configuration object name.
-  if (!$name) {
-    $name = strtok($config_name, '.');
-  }
-
-  // Load and set default configuration values.
-  $file = new FileStorage(drupal_get_path($type, $name) . '/config');
-  if (!$file->exists($config_name)) {
-    return FALSE;
-  }
-
-  // Apply and save the default values.
-  $config->setData($file->read($config_name))->save();
-  return TRUE;
-}
-
-/**
- * Updates 7.x variables to state records.
- *
- * Provides a generalized method to migrate variables from 7.x to 8.x's
- * \Drupal::state() system.
- *
- * @param array $variable_map
- *   An associative array that maps old variables names to new state record
- *   names; e.g.:
- *   @code
- *     array('old_variable' => 'extension.new_name')
- *   @endcode
- *   This would migrate the value contained in variable name 'old_variable' into
- *   the state item 'extension.new_name'.
- *   Non-existing variables and variables with NULL values are omitted.
- */
-function update_variables_to_state(array $variable_map) {
-  foreach ($variable_map as $variable_name => $state_name) {
-    if (NULL !== $value = update_variable_get($variable_name)) {
-      \Drupal::state()->set($state_name, $value);
-    }
-  }
-
-  // Delete the migrated variables.
-  db_delete('variable')
-    ->condition('name', array_keys($variable_map))
-    ->execute();
-}
-
-/**
  * Helper function to update entities with uuid.
  *
  * @param array $sandbox
diff --git a/core/lib/Drupal.php b/core/lib/Drupal.php
index 9c14801..af16bd5 100644
--- a/core/lib/Drupal.php
+++ b/core/lib/Drupal.php
@@ -87,6 +87,11 @@ class Drupal {
   const CORE_COMPATIBILITY = '8.x';
 
   /**
+   * Core minimum schema version.
+   */
+  const CORE_MINIMUM_SCHEMA_VERSION = 8000;
+
+  /**
    * The currently active container object.
    *
    * @var \Symfony\Component\DependencyInjection\ContainerInterface
diff --git a/core/lib/Drupal/Core/Extension/ExtensionSchemaVersionException.php b/core/lib/Drupal/Core/Extension/ExtensionSchemaVersionException.php
new file mode 100644
index 0000000..2b166ac
--- /dev/null
+++ b/core/lib/Drupal/Core/Extension/ExtensionSchemaVersionException.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Extension\ExtensionSchemaVersionException.
+ */
+
+namespace Drupal\Core\Extension;
+
+/**
+ * Exception thrown when the extension's schema version is not allowed.
+ */
+class ExtensionSchemaVersionException extends \Exception { }
diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php
index 5b3d2b9..e69ec31 100644
--- a/core/lib/Drupal/Core/Extension/ModuleHandler.php
+++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php
@@ -627,10 +627,13 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
         // Now install the module's schema if necessary.
         drupal_install_schema($module);
 
-        // Set the schema version to the number of the last update provided
-        // by the module.
+        // Set the schema version to the number of the last update provided by
+        // the module, or the minimum core schema version.
+        $version = \Drupal::CORE_MINIMUM_SCHEMA_VERSION;
         $versions = drupal_get_schema_versions($module);
-        $version = $versions ? max($versions) : SCHEMA_INSTALLED;
+        if ($versions) {
+          $version = max(max($versions), $version);
+        }
 
         // Install default configuration of the module.
         config_install_default_config('module', $module);
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigUpgradeTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigUpgradeTest.php
deleted file mode 100644
index e95f134..0000000
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigUpgradeTest.php
+++ /dev/null
@@ -1,123 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\config\Tests\ConfigUpgradeTest.
- */
-
-namespace Drupal\config\Tests;
-
-use Drupal\Core\Config\ConfigException;
-use Drupal\simpletest\WebTestBase;
-
-/**
- * Tests migration of variables into configuration objects.
- */
-class ConfigUpgradeTest extends WebTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = array('config_upgrade');
-
-  protected $testContent = 'Olá, Sao Paulo!';
-
-  public static function getInfo() {
-    return array(
-      'name' => 'Variable migration',
-      'description' => 'Tests migration of variables into configuration objects.',
-      'group' => 'Configuration',
-    );
-  }
-
-  function setUp() {
-    parent::setUp();
-    require_once DRUPAL_ROOT . '/core/includes/update.inc';
-  }
-
-  /**
-   * Tests update_variables_to_config().
-   */
-  function testConfigurationUpdate() {
-    // Ensure that the variable table has the object. The variable table will
-    // remain in place for Drupal 8 to provide an upgrade path for overridden
-    // variables.
-    db_insert('variable')
-      ->fields(array('name', 'value'))
-      ->values(array('config_upgrade_foo', serialize($this->testContent)))
-      ->values(array('config_upgrade_bar', serialize($this->testContent)))
-      ->execute();
-
-    // Perform migration.
-    update_variables_to_config('config_upgrade.test', array(
-      'config_upgrade_bar' => 'parent.bar',
-      'config_upgrade_foo' => 'foo',
-      // A default configuration value for which no variable exists.
-      'config_upgrade_baz' => 'parent.baz',
-    ));
-
-    // Verify that variables have been converted and default values exist.
-    $config = \Drupal::config('config_upgrade.test');
-    $this->assertIdentical($config->get('foo'), $this->testContent);
-    $this->assertIdentical($config->get('parent.bar'), $this->testContent);
-    $this->assertIdentical($config->get('parent.baz'), 'Baz');
-
-    // Verify that variables have been deleted.
-    $variables = db_query('SELECT name FROM {variable} WHERE name IN (:names)', array(':names' => array('config_upgrade_bar', 'config_upgrade_foo')))->fetchCol();
-    $this->assertFalse($variables);
-
-    // Add another variable to migrate into the same config object.
-    db_insert('variable')
-      ->fields(array('name', 'value'))
-      ->values(array('config_upgrade_additional', serialize($this->testContent)))
-      ->execute();
-
-    // Perform migration into the exsting config object.
-    update_variables_to_config('config_upgrade.test', array(
-      'config_upgrade_additional' => 'parent.additional',
-    ));
-
-    // Verify that new variables have been converted and existing still exist.
-    $config = \Drupal::config('config_upgrade.test');
-    $this->assertIdentical($config->get('foo'), $this->testContent);
-    $this->assertIdentical($config->get('parent.bar'), $this->testContent);
-    $this->assertIdentical($config->get('parent.baz'), 'Baz');
-    $this->assertIdentical($config->get('parent.additional'), $this->testContent);
-
-    // Verify that variables have been deleted.
-    $variables = db_query('SELECT name FROM {variable} WHERE name IN (:names)', array(':names' => array('config_upgrade_additional')))->fetchCol();
-    $this->assertFalse($variables);
-
-    // Verify that a default module configuration file is required to exist.
-    try {
-      update_variables_to_config('config_upgrade.missing.default.config', array());
-      $this->fail('Exception was not thrown on missing default module configuration file.');
-    }
-    catch (ConfigException $e) {
-      $this->pass('Exception was thrown on missing default module configuration file.');
-    }
-
-    // For this test it is essential that update_variables_to_config has already
-    // run on the config object.
-    \Drupal::config('config_upgrade.test')
-      ->set('numeric_keys.403', '')
-      ->set('numeric_keys.404', '')
-      ->save();
-
-    db_insert('variable')
-      ->fields(array('name', 'value'))
-      ->values(array('config_upgrade_403', serialize('custom403')))
-      ->values(array('config_upgrade_404', serialize('custom404')))
-      ->execute();
-
-    // Perform migration.
-    update_variables_to_config('config_upgrade.test', array(
-      'config_upgrade_403' => 'numeric_keys.403',
-      'config_upgrade_404' => 'numeric_keys.404',
-    ));
-
-    $this->assertIdentical(\Drupal::config('config_upgrade.test')->get('numeric_keys'), array(403 => 'custom403', 404 => 'custom404'));
-  }
-}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Update/DependencyHookInvocationTest.php b/core/modules/system/lib/Drupal/system/Tests/Update/DependencyHookInvocationTest.php
index 154643b..f9b0a86 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Update/DependencyHookInvocationTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Update/DependencyHookInvocationTest.php
@@ -19,7 +19,7 @@ class DependencyHookInvocationTest extends WebTestBase {
    *
    * @var array
    */
-  public static $modules = array('update_test_1', 'update_test_2');
+  public static $modules = array('update_test_0', 'update_test_1', 'update_test_2');
 
   public static function getInfo() {
     return array(
@@ -39,8 +39,8 @@ function setUp() {
    */
   function testHookUpdateDependencies() {
     $update_dependencies = update_retrieve_dependencies();
-    $this->assertTrue($update_dependencies['system'][8000]['update_test_1'] == 8000, 'An update function that has a dependency on two separate modules has the first dependency recorded correctly.');
-    $this->assertTrue($update_dependencies['system'][8000]['update_test_2'] == 8001, 'An update function that has a dependency on two separate modules has the second dependency recorded correctly.');
-    $this->assertTrue($update_dependencies['system'][8001]['update_test_1'] == 8002, 'An update function that depends on more than one update from the same module only has the dependency on the higher-numbered update function recorded.');
+    $this->assertTrue($update_dependencies['update_test_0'][8001]['update_test_1'] == 8001, 'An update function that has a dependency on two separate modules has the first dependency recorded correctly.');
+    $this->assertTrue($update_dependencies['update_test_0'][8001]['update_test_2'] == 8002, 'An update function that has a dependency on two separate modules has the second dependency recorded correctly.');
+    $this->assertTrue($update_dependencies['update_test_0'][8002]['update_test_1'] == 8003, 'An update function that depends on more than one update from the same module only has the dependency on the higher-numbered update function recorded.');
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Update/DependencyMissingTest.php b/core/modules/system/lib/Drupal/system/Tests/Update/DependencyMissingTest.php
index 6c71371..167beea 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Update/DependencyMissingTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Update/DependencyMissingTest.php
@@ -19,7 +19,7 @@ class DependencyMissingTest extends WebTestBase {
    *
    * @var array
    */
-  public static $modules = array('update_test_2');
+  public static $modules = array('update_test_0', 'update_test_2');
 
   public static function getInfo() {
     return array(
@@ -38,11 +38,11 @@ function setUp() {
 
   function testMissingUpdate() {
     $starting_updates = array(
-      'update_test_2' => 8000,
+      'update_test_2' => 8001,
     );
     $update_graph = update_resolve_dependencies($starting_updates);
-    $this->assertTrue($update_graph['update_test_2_update_8000']['allowed'], "The module's first update function is allowed to run, since it does not have any missing dependencies.");
-    $this->assertFalse($update_graph['update_test_2_update_8001']['allowed'], "The module's second update function is not allowed to run, since it has a direct dependency on a missing update.");
-    $this->assertFalse($update_graph['update_test_2_update_8002']['allowed'], "The module's third update function is not allowed to run, since it has an indirect dependency on a missing update.");
+    $this->assertTrue($update_graph['update_test_2_update_8001']['allowed'], "The module's first update function is allowed to run, since it does not have any missing dependencies.");
+    $this->assertFalse($update_graph['update_test_2_update_8002']['allowed'], "The module's second update function is not allowed to run, since it has a direct dependency on a missing update.");
+    $this->assertFalse($update_graph['update_test_2_update_8003']['allowed'], "The module's third update function is not allowed to run, since it has an indirect dependency on a missing update.");
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Update/DependencyOrderingTest.php b/core/modules/system/lib/Drupal/system/Tests/Update/DependencyOrderingTest.php
index b007546..5667be0 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Update/DependencyOrderingTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Update/DependencyOrderingTest.php
@@ -19,7 +19,7 @@ class DependencyOrderingTest extends WebTestBase {
    *
    * @var array
    */
-  public static $modules = array('update_test_1', 'update_test_2', 'update_test_3');
+  public static $modules = array('update_test_0', 'update_test_1', 'update_test_2', 'update_test_3');
 
   public static function getInfo() {
     return array(
@@ -39,12 +39,12 @@ function setUp() {
    */
   function testUpdateOrderingSingleModule() {
     $starting_updates = array(
-      'update_test_1' => 8000,
+      'update_test_1' => 8001,
     );
     $expected_updates = array(
-      'update_test_1_update_8000',
       'update_test_1_update_8001',
       'update_test_1_update_8002',
+      'update_test_1_update_8003',
     );
     $actual_updates = array_keys(update_resolve_dependencies($starting_updates));
     $this->assertEqual($expected_updates, $actual_updates, 'Updates within a single module run in the correct order.');
@@ -55,14 +55,14 @@ function testUpdateOrderingSingleModule() {
    */
   function testUpdateOrderingModuleInterdependency() {
     $starting_updates = array(
-      'update_test_2' => 8000,
-      'update_test_3' => 8000,
+      'update_test_2' => 8001,
+      'update_test_3' => 8001,
     );
     $update_order = array_keys(update_resolve_dependencies($starting_updates));
     // Make sure that each dependency is satisfied.
-    $first_dependency_satisfied = array_search('update_test_2_update_8000', $update_order) < array_search('update_test_3_update_8000', $update_order);
+    $first_dependency_satisfied = array_search('update_test_2_update_8001', $update_order) < array_search('update_test_3_update_8001', $update_order);
     $this->assertTrue($first_dependency_satisfied, 'The dependency of the second module on the first module is respected by the update function order.');
-    $second_dependency_satisfied = array_search('update_test_3_update_8000', $update_order) < array_search('update_test_2_update_8001', $update_order);
+    $second_dependency_satisfied = array_search('update_test_3_update_8001', $update_order) < array_search('update_test_2_update_8002', $update_order);
     $this->assertTrue($second_dependency_satisfied, 'The dependency of the first module on the second module is respected by the update function order.');
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php b/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php
index d581147..65d9224 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php
@@ -99,7 +99,7 @@ function testRequirements() {
     $this->assertNoText('This is a requirements warning provided by the update_script_test module.');
     $this->drupalPostForm(NULL, array(), t('Continue'));
     $this->drupalPostForm(NULL, array(), 'Apply pending updates');
-    $this->assertText(t('The update_script_test_update_8000() update was executed successfully.'), 'End of update process was reached.');
+    $this->assertText(t('The update_script_test_update_8001() update was executed successfully.'), 'End of update process was reached.');
     // Confirm that all caches were cleared.
     $this->assertText(t('hook_cache_flush() invoked for update_script_test.module.'), 'Caches were cleared after resolving a requirements warning and applying updates.');
 
@@ -165,7 +165,10 @@ function testNoUpdateFunctionality() {
    * Tests update.php after performing a successful update.
    */
   function testSuccessfulUpdateFunctionality() {
-    drupal_set_installed_schema_version('update_script_test', drupal_get_installed_schema_version('update_script_test') - 1);
+    // Set the installed schema version to one less than the current update.
+    // Reset the static cache to ensure we have the most current setting.
+    drupal_set_installed_schema_version('update_script_test', drupal_get_installed_schema_version('update_script_test', TRUE) - 1);
+
     // Click through update.php with 'administer software updates' permission.
     $this->drupalLogin($this->update_user);
     $this->drupalPostForm($this->update_url, array(), t('Continue'), array('external' => TRUE));
@@ -178,7 +181,10 @@ function testSuccessfulUpdateFunctionality() {
     $this->clickLink('Front page');
     $this->assertResponse(200);
 
-    drupal_set_installed_schema_version('update_script_test', drupal_get_installed_schema_version('update_script_test') - 1);
+    // Set the installed schema version to one less than the current update.
+    // Reset the static cache to ensure we have the most current setting.
+    drupal_set_installed_schema_version('update_script_test', drupal_get_installed_schema_version('update_script_test', TRUE) - 1);
+
     // Click through update.php with 'access administration pages' and
     // 'access site reports' permissions.
     $admin_user = $this->drupalCreateUser(array('administer software updates', 'access administration pages', 'access site reports'));
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index cabea75..c5ee902 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -2192,22 +2192,24 @@ function hook_install() {
  * The numbers are composed of three parts:
  * - 1 digit for Drupal core compatibility.
  * - 1 digit for your module's major release version (e.g., is this the 8.x-1.*
- *   (1) or 8.x-2.* (2) series of your module?). This digit should be 0 for
- *   initial porting of your module to a new Drupal core API.
- * - 2 digits for sequential counting, starting with 00.
+ *   (1) or 8.x-2.* (2) series of your module).
+ * - 2 digits for sequential counting, starting with 01.
  *
  * Examples:
- * - mymodule_update_8000(): This is the required update for mymodule to run
- *   with Drupal core API 8.x when upgrading from Drupal core API 7.x.
  * - mymodule_update_8100(): This is the first update to get the database ready
  *   to run mymodule 8.x-1.*.
  * - mymodule_update_8200(): This is the first update to get the database ready
- *   to run mymodule 8.x-2.*. Users can directly update from 7.x-2.* to 8.x-2.*
- *   and they get all 80xx and 82xx updates, but not 81xx updates, because
- *   those reside in the 8.x-1.x branch only.
+ *   to run mymodule 8.x-2.*.
+ *
+ * As of Drupal 8.0, the database upgrade system no longer supports updating a
+ * database from an earlier major version of Drupal: update.php can be used to
+ * upgrade from 7.x-1.x to 7.x-2.x, or 8.x-1.x to 8.x-2.x, but not from 7.x to
+ * 8.x. Therefore, only update hooks numbered 8001 or later will run for
+ * Drupal 8. 8000 is reserved for the minimum core schema version and defining
+ * mymodule_update_8000() will result in an exception. Use the
+ * @link https://drupal.org/node/2127611 Migration API @endlink instead to
+ * migrate data from an earlier major version of Drupal.
  *
- * A good rule of thumb is to remove updates older than two major releases of
- * Drupal. See hook_update_last_removed() to notify Drupal about the removals.
  * For further information about releases and release numbers see:
  * @link http://drupal.org/node/711070 Maintaining a drupal.org project with Git @endlink
  *
@@ -2332,21 +2334,21 @@ function hook_update_N(&$sandbox) {
  * @see hook_update_N()
  */
 function hook_update_dependencies() {
-  // Indicate that the mymodule_update_8000() function provided by this module
-  // must run after the another_module_update_8002() function provided by the
+  // Indicate that the mymodule_update_8001() function provided by this module
+  // must run after the another_module_update_8003() function provided by the
   // 'another_module' module.
-  $dependencies['mymodule'][8000] = array(
-    'another_module' => 8002,
+  $dependencies['mymodule'][8001] = array(
+    'another_module' => 8003,
   );
-  // Indicate that the mymodule_update_8001() function provided by this module
-  // must run before the yet_another_module_update_8004() function provided by
+  // Indicate that the mymodule_update_8002() function provided by this module
+  // must run before the yet_another_module_update_8005() function provided by
   // the 'yet_another_module' module. (Note that declaring dependencies in this
   // direction should be done only in rare situations, since it can lead to the
   // following problem: If a site has already run the yet_another_module
   // module's database updates before it updates its codebase to pick up the
   // newest mymodule code, then the dependency declared here will be ignored.)
-  $dependencies['yet_another_module'][8004] = array(
-    'mymodule' => 8001,
+  $dependencies['yet_another_module'][8005] = array(
+    'mymodule' => 8002,
   );
   return $dependencies;
 }
@@ -2368,9 +2370,9 @@ function hook_update_dependencies() {
  * @see hook_update_N()
  */
 function hook_update_last_removed() {
-  // We've removed the 5.x-1.x version of mymodule, including database updates.
-  // The next update function is mymodule_update_5200().
-  return 5103;
+  // We've removed the 8.x-1.x version of mymodule, including database updates.
+  // The next update function is mymodule_update_8200().
+  return 8103;
 }
 
 /**
diff --git a/core/modules/system/tests/modules/config_upgrade/config/config_upgrade.test.yml b/core/modules/system/tests/modules/config_upgrade/config/config_upgrade.test.yml
deleted file mode 100644
index fc448c1..0000000
--- a/core/modules/system/tests/modules/config_upgrade/config/config_upgrade.test.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-parent:
-  bar: Bar
-  baz: Baz
-foo: Foo
-numeric_keys:
-  403: ''
-  404: ''
diff --git a/core/modules/system/tests/modules/config_upgrade/config_upgrade.info.yml b/core/modules/system/tests/modules/config_upgrade/config_upgrade.info.yml
deleted file mode 100644
index b439c46..0000000
--- a/core/modules/system/tests/modules/config_upgrade/config_upgrade.info.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-name: 'Config upgrade tests'
-type: module
-description: 'A support module for update_variables_to_config testing.'
-core: 8.x
-package: Testing
-version: VERSION
-hidden: true
diff --git a/core/modules/system/tests/modules/config_upgrade/config_upgrade.module b/core/modules/system/tests/modules/config_upgrade/config_upgrade.module
deleted file mode 100644
index 461e96e..0000000
--- a/core/modules/system/tests/modules/config_upgrade/config_upgrade.module
+++ /dev/null
@@ -1,6 +0,0 @@
-<?php
-
-/**
- * @file
- * A support module for update_variables_to_config() testing.
- */
diff --git a/core/modules/system/tests/modules/update_script_test/update_script_test.install b/core/modules/system/tests/modules/update_script_test/update_script_test.install
index 594dfa3..d09f5a9 100644
--- a/core/modules/system/tests/modules/update_script_test/update_script_test.install
+++ b/core/modules/system/tests/modules/update_script_test/update_script_test.install
@@ -40,6 +40,6 @@ function update_script_test_requirements($phase) {
 /**
  * Dummy update function to run during the tests.
  */
-function update_script_test_update_8000() {
-  return t('The update_script_test_update_8000() update was executed successfully.');
+function update_script_test_update_8001() {
+  return t('The update_script_test_update_8001() update was executed successfully.');
 }
diff --git a/core/modules/system/tests/modules/update_test_0/update_test_0.info.yml b/core/modules/system/tests/modules/update_test_0/update_test_0.info.yml
new file mode 100644
index 0000000..d9f07cd
--- /dev/null
+++ b/core/modules/system/tests/modules/update_test_0/update_test_0.info.yml
@@ -0,0 +1,7 @@
+name: 'Update test 0'
+type: module
+description: 'Support module for update testing.'
+package: Testing
+version: VERSION
+core: 8.x
+hidden: true
diff --git a/core/modules/system/tests/modules/update_test_0/update_test_0.install b/core/modules/system/tests/modules/update_test_0/update_test_0.install
new file mode 100644
index 0000000..16e0c38
--- /dev/null
+++ b/core/modules/system/tests/modules/update_test_0/update_test_0.install
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Install, update and uninstall functions for the update_test_0 module.
+ */
+
+/**
+ * Dummy update_test_0 update 8001.
+ */
+function update_test_0_update_8001() {
+}
+
+/**
+ * Dummy update_test_0 update 8002.
+ */
+function update_test_0_update_8002() {
+}
+
+/**
+ * Dummy update_test_0 update 8003.
+ */
+function update_test_0_update_8003() {
+}
diff --git a/core/modules/system/tests/modules/update_test_0/update_test_0.module b/core/modules/system/tests/modules/update_test_0/update_test_0.module
new file mode 100644
index 0000000..b3d9bbc
--- /dev/null
+++ b/core/modules/system/tests/modules/update_test_0/update_test_0.module
@@ -0,0 +1 @@
+<?php
diff --git a/core/modules/system/tests/modules/update_test_1/update_test_1.install b/core/modules/system/tests/modules/update_test_1/update_test_1.install
index bfb7170..7ef5d98 100644
--- a/core/modules/system/tests/modules/update_test_1/update_test_1.install
+++ b/core/modules/system/tests/modules/update_test_1/update_test_1.install
@@ -15,33 +15,28 @@ function update_test_1_update_dependencies() {
   // These dependencies are used in combination with those declared in
   // update_test_2_update_dependencies() for the sole purpose of testing that
   // the results of hook_update_dependencies() are collected correctly and have
-  // the correct array structure. Therefore, we use updates from System module
-  // (which have already run), so that they will not get in the way of other
-  // tests.
-  $dependencies['system'][8000] = array(
-    // Compare to update_test_2_update_dependencies(), where the same System
-    // module update function is forced to depend on an update function from a
-    // different module. This allows us to test that both dependencies are
-    // correctly recorded.
-    'update_test_1' => 8000,
+  // the correct array structure. Therefore, we use updates from the
+  // update_test_0 module (which will be installed first) that they will not
+  // get in the way of other tests.
+  $dependencies['update_test_0'][8001] = array(
+    // Compare to update_test_2_update_dependencies(), where the same
+    // update_test_0 module update function is forced to depend on an update
+    // function from a different module. This allows us to test that both
+    // dependencies are correctly recorded.
+    'update_test_1' => 8001,
   );
-  $dependencies['system'][8001] = array(
-    // Compare to update_test_2_update_dependencies(), where the same System
-    // module update function is forced to depend on a different update
-    // function within the same module. This allows us to test that only the
-    // dependency on the higher-numbered update function is recorded.
-    'update_test_1' => 8002,
+  $dependencies['update_test_0'][8002] = array(
+    // Compare to update_test_2_update_dependencies(), where the same
+    // update_test_0 module update function is forced to depend on a
+    // different update function within the same module. This allows us to
+    // test that only the dependency on the higher-numbered update function
+    // is recorded.
+    'update_test_1' => 8003,
   );
   return $dependencies;
 }
 
 /**
- * Dummy update_test_1 update 8000.
- */
-function update_test_1_update_8000() {
-}
-
-/**
  * Dummy update_test_1 update 8001.
  */
 function update_test_1_update_8001() {
@@ -52,3 +47,9 @@ function update_test_1_update_8001() {
  */
 function update_test_1_update_8002() {
 }
+
+/**
+ * Dummy update_test_1 update 8003.
+ */
+function update_test_1_update_8003() {
+}
diff --git a/core/modules/system/tests/modules/update_test_2/update_test_2.install b/core/modules/system/tests/modules/update_test_2/update_test_2.install
index c73271a..4202720 100644
--- a/core/modules/system/tests/modules/update_test_2/update_test_2.install
+++ b/core/modules/system/tests/modules/update_test_2/update_test_2.install
@@ -14,33 +14,27 @@
 function update_test_2_update_dependencies() {
   // Combined with update_test_3_update_dependencies(), we are declaring here
   // that these two modules run updates in the following order:
-  // 1. update_test_2_update_8000()
-  // 2. update_test_3_update_8000()
-  // 3. update_test_2_update_8001()
-  // 4. update_test_2_update_8002()
-  $dependencies['update_test_2'][8001] = array(
-    'update_test_3' => 8000,
+  // 1. update_test_2_update_8001()
+  // 2. update_test_3_update_8001()
+  // 3. update_test_2_update_8002()
+  // 4. update_test_2_update_8003()
+  $dependencies['update_test_2'][8002] = array(
+    'update_test_3' => 8001,
   );
 
   // These are coordinated with the corresponding dependencies declared in
   // update_test_1_update_dependencies().
-  $dependencies['system'][8000] = array(
-    'update_test_2' => 8001,
+  $dependencies['update_test_0'][8001] = array(
+    'update_test_2' => 8002,
   );
-  $dependencies['system'][8001] = array(
-    'update_test_1' => 8001,
+  $dependencies['update_test_0'][8002] = array(
+    'update_test_1' => 8002,
   );
 
   return $dependencies;
 }
 
 /**
- * Dummy update_test_2 update 8000.
- */
-function update_test_2_update_8000() {
-}
-
-/**
  * Dummy update_test_2 update 8001.
  */
 function update_test_2_update_8001() {
@@ -51,3 +45,9 @@ function update_test_2_update_8001() {
  */
 function update_test_2_update_8002() {
 }
+
+/**
+ * Dummy update_test_2 update 8003.
+ */
+function update_test_2_update_8003() {
+}
diff --git a/core/modules/system/tests/modules/update_test_3/update_test_3.install b/core/modules/system/tests/modules/update_test_3/update_test_3.install
index 96830c8..ae2da4b 100644
--- a/core/modules/system/tests/modules/update_test_3/update_test_3.install
+++ b/core/modules/system/tests/modules/update_test_3/update_test_3.install
@@ -11,14 +11,14 @@
  * @see update_test_2_update_dependencies()
  */
 function update_test_3_update_dependencies() {
-  $dependencies['update_test_3'][8000] = array(
-    'update_test_2' => 8000,
+  $dependencies['update_test_3'][8001] = array(
+    'update_test_2' => 8001,
   );
   return $dependencies;
 }
 
 /**
- * Dummy update_test_3 update 8000.
+ * Dummy update_test_3 update 8001.
  */
-function update_test_3_update_8000() {
+function update_test_3_update_8001() {
 }
diff --git a/core/update.php b/core/update.php
index 527a703..a254c17 100644
--- a/core/update.php
+++ b/core/update.php
@@ -391,10 +391,6 @@ function update_check_requirements($skip_warnings = FALSE) {
   install_goto('core/update.php?op=info');
 }
 
-// Allow update_fix_d8_requirements() to run before code that can break on a
-// Drupal 7 database.
-drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE);
-update_fix_d8_requirements();
 drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 drupal_maintenance_theme();
 
