health: Add wear-level-threshold to HealthConfig

"wear-level-threshold" is an existing field in cros-config. Add this
field to HealthConfig in Boxster as well.

In addition, refactor `_create_health()` in sw_config.star to enable
creating HealthConfig proto with multiple routines.

BUG=b:208579539
TEST=./generate.sh
TEST=./run_py_unittests.sh && ./run_go_unittests.sh

Cq-Depend: chromium:3922914
Change-Id: Ic3a7b66ebde71ecd4ad424203bc1f456f2a83505
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/config/+/3935987
Reviewed-by: Sam McNally <sammc@chromium.org>
Commit-Queue: Denny Huang <dennyh@google.com>
Reviewed-by: Jack Rosenthal <jrosenth@chromium.org>
diff --git a/generated/descriptors.json b/generated/descriptors.json
index f9b6ccf..1627bb9 100644
--- a/generated/descriptors.json
+++ b/generated/descriptors.json
@@ -8208,12 +8208,32 @@
             {
               "field": [
                 {
+                  "jsonName": "wearLevelThreshold",
+                  "label": "LABEL_OPTIONAL",
+                  "name": "wear_level_threshold",
+                  "number": 1,
+                  "type": "TYPE_UINT32"
+                }
+              ],
+              "name": "NvmeWearLevel"
+            },
+            {
+              "field": [
+                {
                   "jsonName": "batteryHealth",
                   "label": "LABEL_OPTIONAL",
                   "name": "battery_health",
                   "number": 1,
                   "type": "TYPE_MESSAGE",
                   "typeName": ".chromiumos.config.api.software.HealthConfig.BatteryHealth"
+                },
+                {
+                  "jsonName": "nvmeWearLevel",
+                  "label": "LABEL_OPTIONAL",
+                  "name": "nvme_wear_level",
+                  "number": 2,
+                  "type": "TYPE_MESSAGE",
+                  "typeName": ".chromiumos.config.api.software.HealthConfig.NvmeWearLevel"
                 }
               ],
               "name": "Routines"
diff --git a/go/api/software/health_config.pb.go b/go/api/software/health_config.pb.go
index 61ee381..61ae626 100644
--- a/go/api/software/health_config.pb.go
+++ b/go/api/software/health_config.pb.go
@@ -231,18 +231,66 @@
 	return 0
 }
 
+type HealthConfig_NvmeWearLevel struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	WearLevelThreshold uint32 `protobuf:"varint,1,opt,name=wear_level_threshold,json=wearLevelThreshold,proto3" json:"wear_level_threshold,omitempty"`
+}
+
+func (x *HealthConfig_NvmeWearLevel) Reset() {
+	*x = HealthConfig_NvmeWearLevel{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_chromiumos_config_api_software_health_config_proto_msgTypes[4]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *HealthConfig_NvmeWearLevel) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HealthConfig_NvmeWearLevel) ProtoMessage() {}
+
+func (x *HealthConfig_NvmeWearLevel) ProtoReflect() protoreflect.Message {
+	mi := &file_chromiumos_config_api_software_health_config_proto_msgTypes[4]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use HealthConfig_NvmeWearLevel.ProtoReflect.Descriptor instead.
+func (*HealthConfig_NvmeWearLevel) Descriptor() ([]byte, []int) {
+	return file_chromiumos_config_api_software_health_config_proto_rawDescGZIP(), []int{0, 3}
+}
+
+func (x *HealthConfig_NvmeWearLevel) GetWearLevelThreshold() uint32 {
+	if x != nil {
+		return x.WearLevelThreshold
+	}
+	return 0
+}
+
 type HealthConfig_Routines struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
 	BatteryHealth *HealthConfig_BatteryHealth `protobuf:"bytes,1,opt,name=battery_health,json=batteryHealth,proto3" json:"battery_health,omitempty"`
+	NvmeWearLevel *HealthConfig_NvmeWearLevel `protobuf:"bytes,2,opt,name=nvme_wear_level,json=nvmeWearLevel,proto3" json:"nvme_wear_level,omitempty"`
 }
 
 func (x *HealthConfig_Routines) Reset() {
 	*x = HealthConfig_Routines{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_chromiumos_config_api_software_health_config_proto_msgTypes[4]
+		mi := &file_chromiumos_config_api_software_health_config_proto_msgTypes[5]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -255,7 +303,7 @@
 func (*HealthConfig_Routines) ProtoMessage() {}
 
 func (x *HealthConfig_Routines) ProtoReflect() protoreflect.Message {
-	mi := &file_chromiumos_config_api_software_health_config_proto_msgTypes[4]
+	mi := &file_chromiumos_config_api_software_health_config_proto_msgTypes[5]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -268,7 +316,7 @@
 
 // Deprecated: Use HealthConfig_Routines.ProtoReflect.Descriptor instead.
 func (*HealthConfig_Routines) Descriptor() ([]byte, []int) {
-	return file_chromiumos_config_api_software_health_config_proto_rawDescGZIP(), []int{0, 3}
+	return file_chromiumos_config_api_software_health_config_proto_rawDescGZIP(), []int{0, 4}
 }
 
 func (x *HealthConfig_Routines) GetBatteryHealth() *HealthConfig_BatteryHealth {
@@ -278,6 +326,13 @@
 	return nil
 }
 
+func (x *HealthConfig_Routines) GetNvmeWearLevel() *HealthConfig_NvmeWearLevel {
+	if x != nil {
+		return x.NvmeWearLevel
+	}
+	return nil
+}
+
 var File_chromiumos_config_api_software_health_config_proto protoreflect.FileDescriptor
 
 var file_chromiumos_config_api_software_health_config_proto_rawDesc = []byte{
@@ -286,7 +341,7 @@
 	0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70,
 	0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x6f, 0x73,
 	0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x6f, 0x66, 0x74,
-	0x77, 0x61, 0x72, 0x65, 0x22, 0xbc, 0x04, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43,
+	0x77, 0x61, 0x72, 0x65, 0x22, 0xe4, 0x05, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43,
 	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4e, 0x0a, 0x07, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79,
 	0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75,
 	0x6d, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
@@ -315,17 +370,28 @@
 	0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x5f, 0x77, 0x65, 0x61, 0x72, 0x5f, 0x61, 0x6c, 0x6c, 0x6f,
 	0x77, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x19, 0x70, 0x65, 0x72, 0x63, 0x65,
 	0x6e, 0x74, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x57, 0x65, 0x61, 0x72, 0x41, 0x6c, 0x6c,
-	0x6f, 0x77, 0x65, 0x64, 0x1a, 0x6d, 0x0a, 0x08, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x65, 0x73,
-	0x12, 0x61, 0x0a, 0x0e, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x6c,
-	0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d,
-	0x69, 0x75, 0x6d, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x61, 0x70, 0x69,
-	0x2e, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68,
-	0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x48, 0x65,
-	0x61, 0x6c, 0x74, 0x68, 0x52, 0x0d, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x48, 0x65, 0x61,
-	0x6c, 0x74, 0x68, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69,
-	0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x6f,
-	0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x67, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f,
-	0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x6f, 0x77, 0x65, 0x64, 0x1a, 0x41, 0x0a, 0x0d, 0x4e, 0x76, 0x6d, 0x65, 0x57, 0x65, 0x61, 0x72,
+	0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x30, 0x0a, 0x14, 0x77, 0x65, 0x61, 0x72, 0x5f, 0x6c, 0x65,
+	0x76, 0x65, 0x6c, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x0d, 0x52, 0x12, 0x77, 0x65, 0x61, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x54, 0x68,
+	0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x1a, 0xd1, 0x01, 0x0a, 0x08, 0x52, 0x6f, 0x75, 0x74,
+	0x69, 0x6e, 0x65, 0x73, 0x12, 0x61, 0x0a, 0x0e, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x5f,
+	0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x63,
+	0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+	0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x2e, 0x48, 0x65,
+	0x61, 0x6c, 0x74, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x65,
+	0x72, 0x79, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x0d, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72,
+	0x79, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x62, 0x0a, 0x0f, 0x6e, 0x76, 0x6d, 0x65, 0x5f,
+	0x77, 0x65, 0x61, 0x72, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x3a, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x6f, 0x73, 0x2e, 0x63, 0x6f,
+	0x6e, 0x66, 0x69, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72,
+	0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4e,
+	0x76, 0x6d, 0x65, 0x57, 0x65, 0x61, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x0d, 0x6e, 0x76,
+	0x6d, 0x65, 0x57, 0x65, 0x61, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x42, 0x33, 0x5a, 0x31, 0x67,
+	0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x63,
+	0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+	0x2f, 0x67, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
+	0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -340,24 +406,26 @@
 	return file_chromiumos_config_api_software_health_config_proto_rawDescData
 }
 
-var file_chromiumos_config_api_software_health_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
+var file_chromiumos_config_api_software_health_config_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
 var file_chromiumos_config_api_software_health_config_proto_goTypes = []interface{}{
 	(*HealthConfig)(nil),               // 0: chromiumos.config.api.software.HealthConfig
 	(*HealthConfig_Battery)(nil),       // 1: chromiumos.config.api.software.HealthConfig.Battery
 	(*HealthConfig_CachedVpd)(nil),     // 2: chromiumos.config.api.software.HealthConfig.CachedVpd
 	(*HealthConfig_BatteryHealth)(nil), // 3: chromiumos.config.api.software.HealthConfig.BatteryHealth
-	(*HealthConfig_Routines)(nil),      // 4: chromiumos.config.api.software.HealthConfig.Routines
+	(*HealthConfig_NvmeWearLevel)(nil), // 4: chromiumos.config.api.software.HealthConfig.NvmeWearLevel
+	(*HealthConfig_Routines)(nil),      // 5: chromiumos.config.api.software.HealthConfig.Routines
 }
 var file_chromiumos_config_api_software_health_config_proto_depIdxs = []int32{
 	1, // 0: chromiumos.config.api.software.HealthConfig.battery:type_name -> chromiumos.config.api.software.HealthConfig.Battery
 	2, // 1: chromiumos.config.api.software.HealthConfig.cached_vpd:type_name -> chromiumos.config.api.software.HealthConfig.CachedVpd
-	4, // 2: chromiumos.config.api.software.HealthConfig.routines:type_name -> chromiumos.config.api.software.HealthConfig.Routines
+	5, // 2: chromiumos.config.api.software.HealthConfig.routines:type_name -> chromiumos.config.api.software.HealthConfig.Routines
 	3, // 3: chromiumos.config.api.software.HealthConfig.Routines.battery_health:type_name -> chromiumos.config.api.software.HealthConfig.BatteryHealth
-	4, // [4:4] is the sub-list for method output_type
-	4, // [4:4] is the sub-list for method input_type
-	4, // [4:4] is the sub-list for extension type_name
-	4, // [4:4] is the sub-list for extension extendee
-	0, // [0:4] is the sub-list for field type_name
+	4, // 4: chromiumos.config.api.software.HealthConfig.Routines.nvme_wear_level:type_name -> chromiumos.config.api.software.HealthConfig.NvmeWearLevel
+	5, // [5:5] is the sub-list for method output_type
+	5, // [5:5] is the sub-list for method input_type
+	5, // [5:5] is the sub-list for extension type_name
+	5, // [5:5] is the sub-list for extension extendee
+	0, // [0:5] is the sub-list for field type_name
 }
 
 func init() { file_chromiumos_config_api_software_health_config_proto_init() }
@@ -415,6 +483,18 @@
 			}
 		}
 		file_chromiumos_config_api_software_health_config_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*HealthConfig_NvmeWearLevel); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_chromiumos_config_api_software_health_config_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*HealthConfig_Routines); i {
 			case 0:
 				return &v.state
@@ -433,7 +513,7 @@
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_chromiumos_config_api_software_health_config_proto_rawDesc,
 			NumEnums:      0,
-			NumMessages:   5,
+			NumMessages:   6,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/proto/chromiumos/config/api/software/health_config.proto b/proto/chromiumos/config/api/software/health_config.proto
index 6944799..e7fdb1f 100644
--- a/proto/chromiumos/config/api/software/health_config.proto
+++ b/proto/chromiumos/config/api/software/health_config.proto
@@ -22,8 +22,12 @@
   message BatteryHealth {
     uint32 percent_battery_wear_allowed = 1;
   }
+  message NvmeWearLevel {
+    uint32 wear_level_threshold = 1;
+  }
   message Routines {
     BatteryHealth battery_health = 1;
+    NvmeWearLevel nvme_wear_level = 2;
   }
 
   Battery battery = 1;
diff --git a/python/chromiumos/config/api/software/health_config_pb2.py b/python/chromiumos/config/api/software/health_config_pb2.py
index add828d..d5617ef 100644
--- a/python/chromiumos/config/api/software/health_config_pb2.py
+++ b/python/chromiumos/config/api/software/health_config_pb2.py
@@ -19,7 +19,7 @@
   syntax='proto3',
   serialized_options=b'Z1go.chromium.org/chromiumos/config/go/api/software',
   create_key=_descriptor._internal_create_key,
-  serialized_pb=b'\n2chromiumos/config/api/software/health_config.proto\x12\x1e\x63hromiumos.config.api.software\"\xd1\x03\n\x0cHealthConfig\x12\x45\n\x07\x62\x61ttery\x18\x01 \x01(\x0b\x32\x34.chromiumos.config.api.software.HealthConfig.Battery\x12J\n\ncached_vpd\x18\x02 \x01(\x0b\x32\x36.chromiumos.config.api.software.HealthConfig.CachedVpd\x12G\n\x08routines\x18\x03 \x01(\x0b\x32\x35.chromiumos.config.api.software.HealthConfig.Routines\x1a)\n\x07\x42\x61ttery\x12\x1e\n\x16has_smart_battery_info\x18\x01 \x01(\x08\x1a#\n\tCachedVpd\x12\x16\n\x0ehas_sku_number\x18\x01 \x01(\x08\x1a\x35\n\rBatteryHealth\x12$\n\x1cpercent_battery_wear_allowed\x18\x01 \x01(\r\x1a^\n\x08Routines\x12R\n\x0e\x62\x61ttery_health\x18\x01 \x01(\x0b\x32:.chromiumos.config.api.software.HealthConfig.BatteryHealthB3Z1go.chromium.org/chromiumos/config/go/api/softwareb\x06proto3'
+  serialized_pb=b'\n2chromiumos/config/api/software/health_config.proto\x12\x1e\x63hromiumos.config.api.software\"\xd6\x04\n\x0cHealthConfig\x12\x45\n\x07\x62\x61ttery\x18\x01 \x01(\x0b\x32\x34.chromiumos.config.api.software.HealthConfig.Battery\x12J\n\ncached_vpd\x18\x02 \x01(\x0b\x32\x36.chromiumos.config.api.software.HealthConfig.CachedVpd\x12G\n\x08routines\x18\x03 \x01(\x0b\x32\x35.chromiumos.config.api.software.HealthConfig.Routines\x1a)\n\x07\x42\x61ttery\x12\x1e\n\x16has_smart_battery_info\x18\x01 \x01(\x08\x1a#\n\tCachedVpd\x12\x16\n\x0ehas_sku_number\x18\x01 \x01(\x08\x1a\x35\n\rBatteryHealth\x12$\n\x1cpercent_battery_wear_allowed\x18\x01 \x01(\r\x1a-\n\rNvmeWearLevel\x12\x1c\n\x14wear_level_threshold\x18\x01 \x01(\r\x1a\xb3\x01\n\x08Routines\x12R\n\x0e\x62\x61ttery_health\x18\x01 \x01(\x0b\x32:.chromiumos.config.api.software.HealthConfig.BatteryHealth\x12S\n\x0fnvme_wear_level\x18\x02 \x01(\x0b\x32:.chromiumos.config.api.software.HealthConfig.NvmeWearLevelB3Z1go.chromium.org/chromiumos/config/go/api/softwareb\x06proto3'
 )
 
 
@@ -118,18 +118,18 @@
   serialized_end=456,
 )
 
-_HEALTHCONFIG_ROUTINES = _descriptor.Descriptor(
-  name='Routines',
-  full_name='chromiumos.config.api.software.HealthConfig.Routines',
+_HEALTHCONFIG_NVMEWEARLEVEL = _descriptor.Descriptor(
+  name='NvmeWearLevel',
+  full_name='chromiumos.config.api.software.HealthConfig.NvmeWearLevel',
   filename=None,
   file=DESCRIPTOR,
   containing_type=None,
   create_key=_descriptor._internal_create_key,
   fields=[
     _descriptor.FieldDescriptor(
-      name='battery_health', full_name='chromiumos.config.api.software.HealthConfig.Routines.battery_health', index=0,
-      number=1, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
+      name='wear_level_threshold', full_name='chromiumos.config.api.software.HealthConfig.NvmeWearLevel.wear_level_threshold', index=0,
+      number=1, type=13, cpp_type=3, label=1,
+      has_default_value=False, default_value=0,
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
@@ -146,7 +146,45 @@
   oneofs=[
   ],
   serialized_start=458,
-  serialized_end=552,
+  serialized_end=503,
+)
+
+_HEALTHCONFIG_ROUTINES = _descriptor.Descriptor(
+  name='Routines',
+  full_name='chromiumos.config.api.software.HealthConfig.Routines',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='battery_health', full_name='chromiumos.config.api.software.HealthConfig.Routines.battery_health', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='nvme_wear_level', full_name='chromiumos.config.api.software.HealthConfig.Routines.nvme_wear_level', index=1,
+      number=2, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=506,
+  serialized_end=685,
 )
 
 _HEALTHCONFIG = _descriptor.Descriptor(
@@ -181,7 +219,7 @@
   ],
   extensions=[
   ],
-  nested_types=[_HEALTHCONFIG_BATTERY, _HEALTHCONFIG_CACHEDVPD, _HEALTHCONFIG_BATTERYHEALTH, _HEALTHCONFIG_ROUTINES, ],
+  nested_types=[_HEALTHCONFIG_BATTERY, _HEALTHCONFIG_CACHEDVPD, _HEALTHCONFIG_BATTERYHEALTH, _HEALTHCONFIG_NVMEWEARLEVEL, _HEALTHCONFIG_ROUTINES, ],
   enum_types=[
   ],
   serialized_options=None,
@@ -191,13 +229,15 @@
   oneofs=[
   ],
   serialized_start=87,
-  serialized_end=552,
+  serialized_end=685,
 )
 
 _HEALTHCONFIG_BATTERY.containing_type = _HEALTHCONFIG
 _HEALTHCONFIG_CACHEDVPD.containing_type = _HEALTHCONFIG
 _HEALTHCONFIG_BATTERYHEALTH.containing_type = _HEALTHCONFIG
+_HEALTHCONFIG_NVMEWEARLEVEL.containing_type = _HEALTHCONFIG
 _HEALTHCONFIG_ROUTINES.fields_by_name['battery_health'].message_type = _HEALTHCONFIG_BATTERYHEALTH
+_HEALTHCONFIG_ROUTINES.fields_by_name['nvme_wear_level'].message_type = _HEALTHCONFIG_NVMEWEARLEVEL
 _HEALTHCONFIG_ROUTINES.containing_type = _HEALTHCONFIG
 _HEALTHCONFIG.fields_by_name['battery'].message_type = _HEALTHCONFIG_BATTERY
 _HEALTHCONFIG.fields_by_name['cached_vpd'].message_type = _HEALTHCONFIG_CACHEDVPD
@@ -228,6 +268,13 @@
     })
   ,
 
+  'NvmeWearLevel' : _reflection.GeneratedProtocolMessageType('NvmeWearLevel', (_message.Message,), {
+    'DESCRIPTOR' : _HEALTHCONFIG_NVMEWEARLEVEL,
+    '__module__' : 'chromiumos.config.api.software.health_config_pb2'
+    # @@protoc_insertion_point(class_scope:chromiumos.config.api.software.HealthConfig.NvmeWearLevel)
+    })
+  ,
+
   'Routines' : _reflection.GeneratedProtocolMessageType('Routines', (_message.Message,), {
     'DESCRIPTOR' : _HEALTHCONFIG_ROUTINES,
     '__module__' : 'chromiumos.config.api.software.health_config_pb2'
@@ -242,6 +289,7 @@
 _sym_db.RegisterMessage(HealthConfig.Battery)
 _sym_db.RegisterMessage(HealthConfig.CachedVpd)
 _sym_db.RegisterMessage(HealthConfig.BatteryHealth)
+_sym_db.RegisterMessage(HealthConfig.NvmeWearLevel)
 _sym_db.RegisterMessage(HealthConfig.Routines)
 
 
diff --git a/test/project/fake/fake/config.star b/test/project/fake/fake/config.star
index 06c2cec..b6ef40b 100755
--- a/test/project/fake/fake/config.star
+++ b/test/project/fake/fake/config.star
@@ -219,6 +219,7 @@
     vpd_has_sku_number = True,
     battery_has_smart_battery_info = True,
     routines_battery_health_percent_battery_wear_allowed = 50,
+    routines_nvme_wear_level_wear_level_threshold = 50,
 )
 _SC_NNPALM = sc.create_nnpalm(
     model = "alpha",
diff --git a/test/project/fake/fake/generated/config.jsonproto b/test/project/fake/fake/generated/config.jsonproto
index 5af8980..a2f1ece 100644
--- a/test/project/fake/fake/generated/config.jsonproto
+++ b/test/project/fake/fake/generated/config.jsonproto
@@ -7261,6 +7261,9 @@
         "routines": {
           "batteryHealth": {
             "percentBatteryWearAllowed": 50
+          },
+          "nvmeWearLevel": {
+            "wearLevelThreshold": 50
           }
         }
       },
diff --git a/test/project/fake/fake/sw_build_config/platform/chromeos-config/generated/project-config.json b/test/project/fake/fake/sw_build_config/platform/chromeos-config/generated/project-config.json
index bc50f35..ab77222 100644
--- a/test/project/fake/fake/sw_build_config/platform/chromeos-config/generated/project-config.json
+++ b/test/project/fake/fake/sw_build_config/platform/chromeos-config/generated/project-config.json
@@ -101,6 +101,9 @@
           "routines": {
             "battery-health": {
               "percent-battery-wear-allowed": 50
+            },
+            "nvme-wear-level": {
+              "wear-level-threshold": 50
             }
           }
         },
diff --git a/util/sw_config.star b/util/sw_config.star
index f6195a6..a4dd317 100644
--- a/util/sw_config.star
+++ b/util/sw_config.star
@@ -213,15 +213,26 @@
 def _create_health(
         vpd_has_sku_number = None,
         battery_has_smart_battery_info = None,
-        routines_battery_health_percent_battery_wear_allowed = None):
+        routines_battery_health_percent_battery_wear_allowed = None,
+        routines_nvme_wear_level_wear_level_threshold = None):
     """Builds a HealthConfig proto."""
     routines = None
+    battery_health = None
+    nvme_wear_level = None
     if routines_battery_health_percent_battery_wear_allowed != None:
+        battery_health = health_pb.HealthConfig.BatteryHealth(
+            percent_battery_wear_allowed =
+                routines_battery_health_percent_battery_wear_allowed,
+        )
+    if routines_nvme_wear_level_wear_level_threshold != None:
+        nvme_wear_level = health_pb.HealthConfig.NvmeWearLevel(
+            wear_level_threshold =
+                routines_nvme_wear_level_wear_level_threshold,
+        )
+    if battery_health or nvme_wear_level:
         routines = health_pb.HealthConfig.Routines(
-            battery_health = health_pb.HealthConfig.BatteryHealth(
-                percent_battery_wear_allowed =
-                    routines_battery_health_percent_battery_wear_allowed,
-            ),
+            battery_health = battery_health,
+            nvme_wear_level = nvme_wear_level,
         )
     return health_pb.HealthConfig(
         cached_vpd = health_pb.HealthConfig.CachedVpd(