Support checking MSL
diff --git a/rmi4update/firmware_image.cpp b/rmi4update/firmware_image.cpp
index 6b0323e..ecc2af4 100755
--- a/rmi4update/firmware_image.cpp
+++ b/rmi4update/firmware_image.cpp
@@ -123,6 +123,13 @@
 			m_firmwareBuildID = extract_long(content + 4);
 			memcpy(m_productID, (content + 0x18), RMI_PRODUCT_ID_LENGTH);
 			m_productID[RMI_PRODUCT_ID_LENGTH] = 0;
+			if ((descriptor->major_version == 0) && 
+				(descriptor->minor_version > 0)) {
+				m_hasFirmwareVersion = true;
+				fprintf(stdout, "General Information version : %d.%d\n", descriptor->major_version, descriptor->minor_version);
+				m_firmwareVersion = *(content + 0x26) << 8 | *(content + 0x27);
+				fprintf(stdout, "Firmware version : 0x%x\n", m_firmwareVersion);
+			}
 			break;
 		case FIXED_LOCATION_DATA_CONTAINER:
 			if (sigature_size != 0) {
diff --git a/rmi4update/firmware_image.h b/rmi4update/firmware_image.h
index e4279d5..3558b07 100755
--- a/rmi4update/firmware_image.h
+++ b/rmi4update/firmware_image.h
@@ -110,7 +110,8 @@
 {
 public:
 	FirmwareImage() : m_firmwareBuildID(0), m_packageID(0), m_firmwareData(NULL), m_configData(NULL), m_lockdownData(NULL),
-				m_memBlock(NULL), m_hasSignature(false), m_fldData(NULL), m_fldSize(0), m_globalparaData(NULL), m_globalparaSize(0)
+				m_memBlock(NULL), m_hasSignature(false), m_fldData(NULL), m_fldSize(0), m_globalparaData(NULL), m_globalparaSize(0),
+				m_firmwareVersion(0), m_hasFirmwareVersion(false)
 	{}
 	int Initialize(const char * filename);
 	int VerifyImageMatchesDevice(unsigned long deviceFirmwareSize,
@@ -128,8 +129,10 @@
 	unsigned long GetFirmwareID() { return m_firmwareBuildID; }
 	unsigned long GetFLDSize() { return m_fldSize; }
 	unsigned long GetGlobalParametersSize() { return m_globalparaSize; }
+	unsigned short GetFirmwareVersion() { return m_firmwareVersion; }
 	signature_info *GetSignatureInfo() { return m_signatureInfo; }
 	int VerifyImageProductID(char* deviceProductID);
+	bool IsImageHasFirmwareVersion() { return m_hasFirmwareVersion; }
 
 	bool HasIO() { return m_io; }
 	~FirmwareImage();
@@ -164,6 +167,8 @@
 	unsigned long m_fldSize;
 	unsigned char * m_globalparaData;
 	unsigned long m_globalparaSize;
+	unsigned short m_firmwareVersion;
+	bool m_hasFirmwareVersion;
 
 	signature_info m_signatureInfo[BLv7_MAX];
 };
diff --git a/rmi4update/rmi4update.cpp b/rmi4update/rmi4update.cpp
index 5338234..6091842 100755
--- a/rmi4update/rmi4update.cpp
+++ b/rmi4update/rmi4update.cpp
@@ -158,6 +158,21 @@
 		}
 		fprintf(stdout, "Enable Flash done V7+...\n");
 
+		if (IsBLv87()) {
+			if (m_firmwareImage.IsImageHasFirmwareVersion()) {
+				rc = ReadMSL();
+				fprintf(stdout, "MSL : 0x%x\n", m_MSL);
+				if (m_MSL > m_firmwareImage.GetFirmwareVersion()) {
+					fprintf(stdout, "MSL checking failed. device(0x%x) > image(0x%x)\n", 
+						m_MSL, m_firmwareImage.GetFirmwareVersion());
+					rc = UPDATE_FAIL_MSL_CHECKING;
+					goto reset;
+				} else {
+					fprintf(stdout, "Passing MSL checking\n");
+				}
+			}
+		}
+
 		if (m_bootloaderID[1] >= 10) {
 			fprintf(stdout, "Writing FLD V10...\n");
 			rc = WriteFLDV7();
@@ -1119,7 +1134,7 @@
 		do {
 			Sleep(20);
 			rmi4update_poll();
-			if (IsWriteProtectionSupported()) {
+			if (IsBLv87()) {
 				if (m_flashStatus == WRITE_PROTECTION)
 					return UPDATE_FAIL_WRITE_PROTECTED;
 			}
@@ -1256,7 +1271,7 @@
 		do {
 			Sleep(20);
 			rmi4update_poll();
-			if (IsWriteProtectionSupported()) {
+			if (IsBLv87()) {
 				if (m_flashStatus == WRITE_PROTECTION)
 					return UPDATE_FAIL_WRITE_PROTECTED;
 			}
@@ -1450,7 +1465,7 @@
 	do {
 		Sleep(20);
 		rmi4update_poll();
-		if (IsWriteProtectionSupported()) {
+		if (IsBLv87()) {
 			if (m_flashStatus == WRITE_PROTECTION)
 				return UPDATE_FAIL_WRITE_PROTECTED;
 		}
@@ -1581,7 +1596,7 @@
 	do {
 		Sleep(20);
 		rmi4update_poll();
-		if (IsWriteProtectionSupported()) {
+		if (IsBLv87()) {
 			if (m_flashStatus == WRITE_PROTECTION)
 				return UPDATE_FAIL_WRITE_PROTECTED;
 		}
@@ -1989,7 +2004,7 @@
 	return UPDATE_SUCCESS;
 }
 
-bool RMI4Update::IsWriteProtectionSupported()
+bool RMI4Update::IsBLv87()
 {
 	if ((m_bootloaderID[1] >= 10) ||
 		((m_bootloaderID[1] == 8) && (m_bootloaderID[0] >= 7))){
@@ -1997,3 +2012,19 @@
 	} else 
 		return false;
 }
+
+int RMI4Update::ReadMSL()
+{
+	int rc;
+	unsigned char idStr[3];
+	unsigned short query9Addr = m_f34.GetQueryBase() + 9;
+	unsigned char offset;
+	unsigned char MSL[2];
+
+	rc = m_device.Read(query9Addr, MSL, sizeof(MSL));
+	if (rc != sizeof(MSL))
+		return UPDATE_FAIL_READ_F34_QUERIES;
+
+	m_MSL = MSL[0] << 8 | MSL[1];
+	return UPDATE_SUCCESS;
+}
diff --git a/rmi4update/rmi4update.h b/rmi4update/rmi4update.h
index cfc5d21..ea87653 100755
--- a/rmi4update/rmi4update.h
+++ b/rmi4update/rmi4update.h
@@ -195,7 +195,8 @@
 	int GetFirmwareSize() { return m_blockSize * m_fwBlockCount; }
 	int GetConfigSize() { return m_blockSize * m_configBlockCount; }
 	int WriteSignatureV7(enum signature_BLv7 signature_partition, unsigned char* data, int offset);
-	bool IsWriteProtectionSupported();
+	bool IsBLv87();
+	int ReadMSL();
 
 private:
 	RMIDevice & m_device;
@@ -238,6 +239,10 @@
 	bool m_hasGlobalParameters;
 	/* BL_V7 end */
 
+	/* BL v8.7 */
+	unsigned short m_MSL;
+	/* BL v8.7 end */
+
 	/* for BL V10 */
 	bool m_hasFLD;
 	/* BL_V7 end */
diff --git a/rmi4update/updateutil.h b/rmi4update/updateutil.h
index 8667086..e59d690 100644
--- a/rmi4update/updateutil.h
+++ b/rmi4update/updateutil.h
@@ -52,6 +52,7 @@
 	UPDATE_FAIL_INVALID_PARAMETER,
 	UPDATE_FAIL_OPEN_FIRMWARE_IMAGE,
 	UPDATE_FAIL_WRITE_PROTECTED,
+	UPDATE_FAIL_MSL_CHECKING,
 };
 
 const char * update_err_to_string(int err);