1e7b4ff9317fc4e551cf974684eaa88697de5a28srs// attributes.cc 2e7b4ff9317fc4e551cf974684eaa88697de5a28srs// Class to manage partition attribute codes. These are binary bit fields, 364cbd171067eb34054741bfcd73f0b91d727a371srs// of which only four are currently (2/2011) documented on Wikipedia, and 464cbd171067eb34054741bfcd73f0b91d727a371srs// two others found from other sources. 5e7b4ff9317fc4e551cf974684eaa88697de5a28srs 6e3ee733ff8690af7568dac665bc20ecf869dea1dRoderick W. Smith/* This program is copyright (c) 2009-2013 by Roderick W. Smith. It is distributed 7221e08768de7fe42ba533ca22baf671420569c07srs under the terms of the GNU GPL version 2, as detailed in the COPYING file. */ 8221e08768de7fe42ba533ca22baf671420569c07srs 9e7b4ff9317fc4e551cf974684eaa88697de5a28srs#define __STDC_LIMIT_MACROS 10e7b4ff9317fc4e551cf974684eaa88697de5a28srs#define __STDC_CONSTANT_MACROS 11e7b4ff9317fc4e551cf974684eaa88697de5a28srs 12e7b4ff9317fc4e551cf974684eaa88697de5a28srs#include <stdint.h> 13e7b4ff9317fc4e551cf974684eaa88697de5a28srs#include <stdio.h> 14fed16d043a14e8b86c97a6413aec7281fefcbcb5srs#include <iostream> 1508bb0da07953af605b4918e268272de15ac151aasrs#include <sstream> 169ddc14bb9b154518e2b8384d3f4571cf657c7920srs 17e7b4ff9317fc4e551cf974684eaa88697de5a28srs#include "attributes.h" 189ddc14bb9b154518e2b8384d3f4571cf657c7920srs#include "support.h" 19e7b4ff9317fc4e551cf974684eaa88697de5a28srs 20e7b4ff9317fc4e551cf974684eaa88697de5a28srsusing namespace std; 21e7b4ff9317fc4e551cf974684eaa88697de5a28srs 229ddc14bb9b154518e2b8384d3f4571cf657c7920srsstring Attributes::atNames[NUM_ATR]; 230873e9d0e9345a2c4418b4718db525c9f1111c83srsint Attributes::numAttrs = 0; 240873e9d0e9345a2c4418b4718db525c9f1111c83srs//Attributes::staticInit Attributes::staticInitializer; 250873e9d0e9345a2c4418b4718db525c9f1111c83srs 260873e9d0e9345a2c4418b4718db525c9f1111c83srs// Default constructor 270873e9d0e9345a2c4418b4718db525c9f1111c83srsAttributes::Attributes(void) { 280873e9d0e9345a2c4418b4718db525c9f1111c83srs numAttrs++; 290873e9d0e9345a2c4418b4718db525c9f1111c83srs if (numAttrs == 1) 300873e9d0e9345a2c4418b4718db525c9f1111c83srs Setup(); 310873e9d0e9345a2c4418b4718db525c9f1111c83srs attributes = 0; 320873e9d0e9345a2c4418b4718db525c9f1111c83srs} // constructor 330873e9d0e9345a2c4418b4718db525c9f1111c83srs 340873e9d0e9345a2c4418b4718db525c9f1111c83srs// Alternate constructor 350873e9d0e9345a2c4418b4718db525c9f1111c83srsAttributes::Attributes(const uint64_t a) { 360873e9d0e9345a2c4418b4718db525c9f1111c83srs numAttrs++; 370873e9d0e9345a2c4418b4718db525c9f1111c83srs if (numAttrs == 1) 380873e9d0e9345a2c4418b4718db525c9f1111c83srs Setup(); 390873e9d0e9345a2c4418b4718db525c9f1111c83srs attributes = a; 400873e9d0e9345a2c4418b4718db525c9f1111c83srs} // alternate constructor 41e7b4ff9317fc4e551cf974684eaa88697de5a28srs 420873e9d0e9345a2c4418b4718db525c9f1111c83srs// Destructor. 430873e9d0e9345a2c4418b4718db525c9f1111c83srsAttributes::~Attributes(void) { 440873e9d0e9345a2c4418b4718db525c9f1111c83srs numAttrs--; 450873e9d0e9345a2c4418b4718db525c9f1111c83srs} // Attributes destructor 460873e9d0e9345a2c4418b4718db525c9f1111c83srs 470873e9d0e9345a2c4418b4718db525c9f1111c83srsvoid Attributes::Setup(void) { 489ddc14bb9b154518e2b8384d3f4571cf657c7920srs ostringstream temp; 490873e9d0e9345a2c4418b4718db525c9f1111c83srs 50e7b4ff9317fc4e551cf974684eaa88697de5a28srs // Most bits are undefined, so start by giving them an 51e7b4ff9317fc4e551cf974684eaa88697de5a28srs // appropriate name 529ddc14bb9b154518e2b8384d3f4571cf657c7920srs for (int i = 0; i < NUM_ATR; i++) { 539ddc14bb9b154518e2b8384d3f4571cf657c7920srs temp.str(""); 5408bb0da07953af605b4918e268272de15ac151aasrs temp << "Undefined bit #" << i; 559ddc14bb9b154518e2b8384d3f4571cf657c7920srs Attributes::atNames[i] = temp.str(); 56e7b4ff9317fc4e551cf974684eaa88697de5a28srs } // for 57e7b4ff9317fc4e551cf974684eaa88697de5a28srs 58e7b4ff9317fc4e551cf974684eaa88697de5a28srs // Now reset those names that are defined.... 590873e9d0e9345a2c4418b4718db525c9f1111c83srs atNames[0] = "system partition"; // required for computer to operate 600873e9d0e9345a2c4418b4718db525c9f1111c83srs atNames[1] = "hide from EFI"; 610873e9d0e9345a2c4418b4718db525c9f1111c83srs atNames[2] = "legacy BIOS bootable"; 620873e9d0e9345a2c4418b4718db525c9f1111c83srs atNames[60] = "read-only"; 630873e9d0e9345a2c4418b4718db525c9f1111c83srs atNames[62] = "hidden"; 640873e9d0e9345a2c4418b4718db525c9f1111c83srs atNames[63] = "do not automount"; 650873e9d0e9345a2c4418b4718db525c9f1111c83srs} // Attributes::Setup() 66e7b4ff9317fc4e551cf974684eaa88697de5a28srs 67e7b4ff9317fc4e551cf974684eaa88697de5a28srs// Display current attributes to user 68e7b4ff9317fc4e551cf974684eaa88697de5a28srsvoid Attributes::DisplayAttributes(void) { 699ddc14bb9b154518e2b8384d3f4571cf657c7920srs uint32_t i; 709ddc14bb9b154518e2b8384d3f4571cf657c7920srs int numSet = 0; 71e7b4ff9317fc4e551cf974684eaa88697de5a28srs 72fed16d043a14e8b86c97a6413aec7281fefcbcb5srs cout << "Attribute value is "; 73fed16d043a14e8b86c97a6413aec7281fefcbcb5srs cout.setf(ios::uppercase); 74fed16d043a14e8b86c97a6413aec7281fefcbcb5srs cout.fill('0'); 75fed16d043a14e8b86c97a6413aec7281fefcbcb5srs cout.width(16); 76fed16d043a14e8b86c97a6413aec7281fefcbcb5srs cout << hex << attributes << dec << ". Set fields are:\n"; 77e7b4ff9317fc4e551cf974684eaa88697de5a28srs for (i = 0; i < NUM_ATR; i++) { 789ddc14bb9b154518e2b8384d3f4571cf657c7920srs if ((UINT64_C(1) << i) & attributes) { 790873e9d0e9345a2c4418b4718db525c9f1111c83srs cout << i << " (" << GetAttributeName(i) << ")" << "\n"; 809ddc14bb9b154518e2b8384d3f4571cf657c7920srs numSet++; 81e7b4ff9317fc4e551cf974684eaa88697de5a28srs } // if 82e7b4ff9317fc4e551cf974684eaa88697de5a28srs } // for 83fed16d043a14e8b86c97a6413aec7281fefcbcb5srs cout.fill(' '); 849ddc14bb9b154518e2b8384d3f4571cf657c7920srs if (numSet == 0) 859ddc14bb9b154518e2b8384d3f4571cf657c7920srs cout << " No fields set\n"; 869ddc14bb9b154518e2b8384d3f4571cf657c7920srs cout << "\n"; 87e7b4ff9317fc4e551cf974684eaa88697de5a28srs} // Attributes::DisplayAttributes() 88e7b4ff9317fc4e551cf974684eaa88697de5a28srs 890873e9d0e9345a2c4418b4718db525c9f1111c83srs// Display attributes for a partition. Note that partNum is just passed for 900873e9d0e9345a2c4418b4718db525c9f1111c83srs// immediate display; it's not used to access a particular partition. 910873e9d0e9345a2c4418b4718db525c9f1111c83srsvoid Attributes::ShowAttributes(const uint32_t partNum) { 920873e9d0e9345a2c4418b4718db525c9f1111c83srs uint32_t bitNum; 930873e9d0e9345a2c4418b4718db525c9f1111c83srs bool bitset; 940873e9d0e9345a2c4418b4718db525c9f1111c83srs 950873e9d0e9345a2c4418b4718db525c9f1111c83srs for (bitNum = 0; bitNum < 64; bitNum++) { 960873e9d0e9345a2c4418b4718db525c9f1111c83srs bitset = (UINT64_C(1) << bitNum) & attributes; 970873e9d0e9345a2c4418b4718db525c9f1111c83srs if (bitset) { 980873e9d0e9345a2c4418b4718db525c9f1111c83srs cout << partNum+1 << ":" << bitNum << ":" << bitset 990873e9d0e9345a2c4418b4718db525c9f1111c83srs << " (" << GetAttributeName(bitNum) << ")" << endl; 1000873e9d0e9345a2c4418b4718db525c9f1111c83srs } // if 1010873e9d0e9345a2c4418b4718db525c9f1111c83srs } // for 1020873e9d0e9345a2c4418b4718db525c9f1111c83srs} // Attributes::ShowAttributes 1030873e9d0e9345a2c4418b4718db525c9f1111c83srs 104e7b4ff9317fc4e551cf974684eaa88697de5a28srs// Prompt user for attribute changes 105e7b4ff9317fc4e551cf974684eaa88697de5a28srsvoid Attributes::ChangeAttributes(void) { 1069ddc14bb9b154518e2b8384d3f4571cf657c7920srs int response; 107e7b4ff9317fc4e551cf974684eaa88697de5a28srs uint64_t bitValue; 108e7b4ff9317fc4e551cf974684eaa88697de5a28srs 109fed16d043a14e8b86c97a6413aec7281fefcbcb5srs cout << "Known attributes are:\n"; 1109ddc14bb9b154518e2b8384d3f4571cf657c7920srs ListAttributes(); 1119ddc14bb9b154518e2b8384d3f4571cf657c7920srs cout << "\n"; 112e7b4ff9317fc4e551cf974684eaa88697de5a28srs 113e7b4ff9317fc4e551cf974684eaa88697de5a28srs do { 1149ddc14bb9b154518e2b8384d3f4571cf657c7920srs DisplayAttributes(); 1150873e9d0e9345a2c4418b4718db525c9f1111c83srs response = GetNumber(0, NUM_ATR, 64, 1160873e9d0e9345a2c4418b4718db525c9f1111c83srs "Toggle which attribute field (0-63, 64 or <Enter> to exit): "); 117e7b4ff9317fc4e551cf974684eaa88697de5a28srs if (response != 64) { 1189ddc14bb9b154518e2b8384d3f4571cf657c7920srs bitValue = UINT64_C(1) << response; // Find the integer value of the bit 1199ddc14bb9b154518e2b8384d3f4571cf657c7920srs if (bitValue & attributes) { // bit is set 1209ddc14bb9b154518e2b8384d3f4571cf657c7920srs attributes &= ~bitValue; // so unset it 1219ddc14bb9b154518e2b8384d3f4571cf657c7920srs cout << "Have disabled the '" << atNames[response] << "' attribute.\n"; 122e7b4ff9317fc4e551cf974684eaa88697de5a28srs } else { // bit is not set 1239ddc14bb9b154518e2b8384d3f4571cf657c7920srs attributes |= bitValue; // so set it 124fed16d043a14e8b86c97a6413aec7281fefcbcb5srs cout << "Have enabled the '" << atNames[response] << "' attribute.\n"; 125e7b4ff9317fc4e551cf974684eaa88697de5a28srs } // if/else 126e7b4ff9317fc4e551cf974684eaa88697de5a28srs } // if 127e7b4ff9317fc4e551cf974684eaa88697de5a28srs } while (response != 64); 128e7b4ff9317fc4e551cf974684eaa88697de5a28srs} // Attributes::ChangeAttributes() 129e7b4ff9317fc4e551cf974684eaa88697de5a28srs 1309ddc14bb9b154518e2b8384d3f4571cf657c7920srs// Display all defined attributes on the screen (omits undefined bits). 1319ddc14bb9b154518e2b8384d3f4571cf657c7920srsvoid Attributes::ListAttributes(void) { 1329ddc14bb9b154518e2b8384d3f4571cf657c7920srs uint32_t bitNum; 1339ddc14bb9b154518e2b8384d3f4571cf657c7920srs string tempAttr; 1349ddc14bb9b154518e2b8384d3f4571cf657c7920srs 1359ddc14bb9b154518e2b8384d3f4571cf657c7920srs for (bitNum = 0; bitNum < NUM_ATR; bitNum++) { 1369ddc14bb9b154518e2b8384d3f4571cf657c7920srs tempAttr = GetAttributeName(bitNum); 1379ddc14bb9b154518e2b8384d3f4571cf657c7920srs if (tempAttr.substr(0, 15) != "Undefined bit #" ) 1389ddc14bb9b154518e2b8384d3f4571cf657c7920srs cout << bitNum << ": " << Attributes::GetAttributeName(bitNum) << "\n"; 1399ddc14bb9b154518e2b8384d3f4571cf657c7920srs } // for 1409ddc14bb9b154518e2b8384d3f4571cf657c7920srs} // Attributes::ListAttributes 1419ddc14bb9b154518e2b8384d3f4571cf657c7920srs 1429ddc14bb9b154518e2b8384d3f4571cf657c7920srs// multifaceted attributes access 1439ddc14bb9b154518e2b8384d3f4571cf657c7920srs// returns true upon success, false upon failure 1449ddc14bb9b154518e2b8384d3f4571cf657c7920srsbool Attributes::OperateOnAttributes(const uint32_t partNum, const string& attributeOperator, const string& attributeBits) { 1459ddc14bb9b154518e2b8384d3f4571cf657c7920srs 1469ddc14bb9b154518e2b8384d3f4571cf657c7920srs // attribute access opcode 1479ddc14bb9b154518e2b8384d3f4571cf657c7920srs typedef enum { 1489ddc14bb9b154518e2b8384d3f4571cf657c7920srs ao_or, ao_nand, ao_xor, ao_assignall, // operate on all attributes (bitmask) 1499ddc14bb9b154518e2b8384d3f4571cf657c7920srs ao_unknown, // must be after bitmask operators and before bitnum operators 1509ddc14bb9b154518e2b8384d3f4571cf657c7920srs ao_set, ao_clear, ao_toggle, ao_get // operate on a single attribute (bitnum) 1519ddc14bb9b154518e2b8384d3f4571cf657c7920srs } attribute_opcode_t; // typedef enum 1529ddc14bb9b154518e2b8384d3f4571cf657c7920srs 1539ddc14bb9b154518e2b8384d3f4571cf657c7920srs // translate attribute operator into an attribute opcode 1549ddc14bb9b154518e2b8384d3f4571cf657c7920srs attribute_opcode_t attributeOpcode = ao_unknown; { // opcode is not known yet 1559ddc14bb9b154518e2b8384d3f4571cf657c7920srs if (attributeOperator == "or") attributeOpcode = ao_or; 1569ddc14bb9b154518e2b8384d3f4571cf657c7920srs else if (attributeOperator == "nand") attributeOpcode = ao_nand; 1579ddc14bb9b154518e2b8384d3f4571cf657c7920srs else if (attributeOperator == "xor") attributeOpcode = ao_xor; 1589ddc14bb9b154518e2b8384d3f4571cf657c7920srs else if (attributeOperator == "=") attributeOpcode = ao_assignall; 1599ddc14bb9b154518e2b8384d3f4571cf657c7920srs else if (attributeOperator == "set") attributeOpcode = ao_set; 1609ddc14bb9b154518e2b8384d3f4571cf657c7920srs else if (attributeOperator == "clear") attributeOpcode = ao_clear; 1619ddc14bb9b154518e2b8384d3f4571cf657c7920srs else if (attributeOperator == "toggle") attributeOpcode = ao_toggle; 1629ddc14bb9b154518e2b8384d3f4571cf657c7920srs else if (attributeOperator == "get") attributeOpcode = ao_get; 1639ddc14bb9b154518e2b8384d3f4571cf657c7920srs else { 1649ddc14bb9b154518e2b8384d3f4571cf657c7920srs cerr << "Unknown attributes operator: " << attributeOperator << endl; 1659ddc14bb9b154518e2b8384d3f4571cf657c7920srs return false; 1669ddc14bb9b154518e2b8384d3f4571cf657c7920srs } // else 1679ddc14bb9b154518e2b8384d3f4571cf657c7920srs } // attributeOpcode 1689ddc14bb9b154518e2b8384d3f4571cf657c7920srs 1699ddc14bb9b154518e2b8384d3f4571cf657c7920srs // get bit mask if operating on entire attribute set 1709ddc14bb9b154518e2b8384d3f4571cf657c7920srs uint64_t attributeBitMask; { if (attributeOpcode < ao_unknown) { 1719ddc14bb9b154518e2b8384d3f4571cf657c7920srs if (1 != sscanf (attributeBits.c_str(), "%qx", (long long unsigned int*) &attributeBitMask)) { 1729ddc14bb9b154518e2b8384d3f4571cf657c7920srs cerr << "Could not convert hex attribute mask" << endl; 1739ddc14bb9b154518e2b8384d3f4571cf657c7920srs return false; 1749ddc14bb9b154518e2b8384d3f4571cf657c7920srs } // if 1759ddc14bb9b154518e2b8384d3f4571cf657c7920srs }} // attributeBitMask, if 1769ddc14bb9b154518e2b8384d3f4571cf657c7920srs 1779ddc14bb9b154518e2b8384d3f4571cf657c7920srs // get bit number and calculate bit mask if operating on a single attribute 1789ddc14bb9b154518e2b8384d3f4571cf657c7920srs int bitNum; { if (attributeOpcode > ao_unknown) { 1799ddc14bb9b154518e2b8384d3f4571cf657c7920srs if (1 != sscanf (attributeBits.c_str(), "%d", &bitNum)) { 1809ddc14bb9b154518e2b8384d3f4571cf657c7920srs cerr << "Could not convert bit number" << endl; 1819ddc14bb9b154518e2b8384d3f4571cf657c7920srs return false; 1829ddc14bb9b154518e2b8384d3f4571cf657c7920srs } // if 1839ddc14bb9b154518e2b8384d3f4571cf657c7920srs const uint64_t one = 1; 1849ddc14bb9b154518e2b8384d3f4571cf657c7920srs attributeBitMask = one << bitNum; 1859ddc14bb9b154518e2b8384d3f4571cf657c7920srs }} // bitNum, if 1869ddc14bb9b154518e2b8384d3f4571cf657c7920srs 1879ddc14bb9b154518e2b8384d3f4571cf657c7920srs switch (attributeOpcode) { 1889ddc14bb9b154518e2b8384d3f4571cf657c7920srs // assign all attributes at once 1899ddc14bb9b154518e2b8384d3f4571cf657c7920srs case ao_assignall: attributes = attributeBitMask; break; 1909ddc14bb9b154518e2b8384d3f4571cf657c7920srs 1919ddc14bb9b154518e2b8384d3f4571cf657c7920srs // set individual attribute(s) 1929ddc14bb9b154518e2b8384d3f4571cf657c7920srs case ao_set: 1939ddc14bb9b154518e2b8384d3f4571cf657c7920srs case ao_or: attributes |= attributeBitMask; break; 1949ddc14bb9b154518e2b8384d3f4571cf657c7920srs 1959ddc14bb9b154518e2b8384d3f4571cf657c7920srs // clear individual attribute(s) 1969ddc14bb9b154518e2b8384d3f4571cf657c7920srs case ao_clear: 1979ddc14bb9b154518e2b8384d3f4571cf657c7920srs case ao_nand: attributes &= ~attributeBitMask; break; 1989ddc14bb9b154518e2b8384d3f4571cf657c7920srs 1999ddc14bb9b154518e2b8384d3f4571cf657c7920srs // toggle individual attribute(s) 2009ddc14bb9b154518e2b8384d3f4571cf657c7920srs case ao_toggle: 2019ddc14bb9b154518e2b8384d3f4571cf657c7920srs case ao_xor: attributes ^= attributeBitMask; break; 2029ddc14bb9b154518e2b8384d3f4571cf657c7920srs 2039ddc14bb9b154518e2b8384d3f4571cf657c7920srs // display a single attribute 2049ddc14bb9b154518e2b8384d3f4571cf657c7920srs case ao_get: { 205ab4b0438394df4ae6bdea86194e254d7d35fdea0srs cout << partNum+1 << ":" << bitNum << ":" 206ab4b0438394df4ae6bdea86194e254d7d35fdea0srs << bool (attributeBitMask & attributes) << endl; 2079ddc14bb9b154518e2b8384d3f4571cf657c7920srs break; 2089ddc14bb9b154518e2b8384d3f4571cf657c7920srs } // case ao_get 2099ddc14bb9b154518e2b8384d3f4571cf657c7920srs 2109ddc14bb9b154518e2b8384d3f4571cf657c7920srs default: break; // will never get here 2119ddc14bb9b154518e2b8384d3f4571cf657c7920srs } // switch 2129ddc14bb9b154518e2b8384d3f4571cf657c7920srs 2139ddc14bb9b154518e2b8384d3f4571cf657c7920srs return true; 2149ddc14bb9b154518e2b8384d3f4571cf657c7920srs} // Attributes::OperateOnAttributes() 2150873e9d0e9345a2c4418b4718db525c9f1111c83srs 2160873e9d0e9345a2c4418b4718db525c9f1111c83srs/******************************* 2170873e9d0e9345a2c4418b4718db525c9f1111c83srs* * 2180873e9d0e9345a2c4418b4718db525c9f1111c83srs* Non-class support functions * 2190873e9d0e9345a2c4418b4718db525c9f1111c83srs* * 2200873e9d0e9345a2c4418b4718db525c9f1111c83srs*******************************/ 2210873e9d0e9345a2c4418b4718db525c9f1111c83srs 2220873e9d0e9345a2c4418b4718db525c9f1111c83srs// Display attributes 2230873e9d0e9345a2c4418b4718db525c9f1111c83srsostream & operator<<(ostream & os, const Attributes & data) { 2240873e9d0e9345a2c4418b4718db525c9f1111c83srs os << data.GetAttributes(); 2250873e9d0e9345a2c4418b4718db525c9f1111c83srs return os; 226699941e25a1fcf0beec124203747c8ed20842989srs} // operator<<() 227