blob: f3cd58527b36e38d04646c4da3293aa334bea3a5 [file] [log] [blame]
srs5694e7b4ff92009-08-18 13:16:10 -04001// attributes.cc
2// Class to manage partition attribute codes. These are binary bit fields,
srs569464cbd172011-03-01 22:03:54 -05003// of which only four are currently (2/2011) documented on Wikipedia, and
4// two others found from other sources.
srs5694e7b4ff92009-08-18 13:16:10 -04005
Roderick W. Smithe3ee7332013-09-24 12:56:11 -04006/* This program is copyright (c) 2009-2013 by Roderick W. Smith. It is distributed
srs5694221e0872009-08-29 15:00:31 -04007 under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
8
srs5694e7b4ff92009-08-18 13:16:10 -04009#define __STDC_LIMIT_MACROS
10#define __STDC_CONSTANT_MACROS
11
srs5694e7b4ff92009-08-18 13:16:10 -040012#include <stdint.h>
13#include <stdio.h>
srs5694fed16d02010-01-27 23:03:40 -050014#include <iostream>
srs569408bb0da2010-02-19 17:19:55 -050015#include <sstream>
srs56949ddc14b2010-08-22 22:44:42 -040016
srs5694e7b4ff92009-08-18 13:16:10 -040017#include "attributes.h"
srs56949ddc14b2010-08-22 22:44:42 -040018#include "support.h"
srs5694e7b4ff92009-08-18 13:16:10 -040019
20using namespace std;
21
srs56949ddc14b2010-08-22 22:44:42 -040022string Attributes::atNames[NUM_ATR];
srs56940873e9d2010-10-07 13:00:45 -040023int Attributes::numAttrs = 0;
24//Attributes::staticInit Attributes::staticInitializer;
srs5694e7b4ff92009-08-18 13:16:10 -040025
srs56940873e9d2010-10-07 13:00:45 -040026// Default constructor
27Attributes::Attributes(void) {
28 numAttrs++;
29 if (numAttrs == 1)
30 Setup();
31 attributes = 0;
32} // constructor
33
34// Alternate constructor
35Attributes::Attributes(const uint64_t a) {
36 numAttrs++;
37 if (numAttrs == 1)
38 Setup();
39 attributes = a;
40} // alternate constructor
41
42// Destructor.
43Attributes::~Attributes(void) {
44 numAttrs--;
45} // Attributes destructor
46
47void Attributes::Setup(void) {
srs56949ddc14b2010-08-22 22:44:42 -040048 ostringstream temp;
srs56940873e9d2010-10-07 13:00:45 -040049
srs5694e7b4ff92009-08-18 13:16:10 -040050 // Most bits are undefined, so start by giving them an
51 // appropriate name
srs56949ddc14b2010-08-22 22:44:42 -040052 for (int i = 0; i < NUM_ATR; i++) {
53 temp.str("");
srs569408bb0da2010-02-19 17:19:55 -050054 temp << "Undefined bit #" << i;
srs56949ddc14b2010-08-22 22:44:42 -040055 Attributes::atNames[i] = temp.str();
srs5694e7b4ff92009-08-18 13:16:10 -040056 } // for
57
58 // Now reset those names that are defined....
srs56940873e9d2010-10-07 13:00:45 -040059 atNames[0] = "system partition"; // required for computer to operate
60 atNames[1] = "hide from EFI";
61 atNames[2] = "legacy BIOS bootable";
62 atNames[60] = "read-only";
63 atNames[62] = "hidden";
64 atNames[63] = "do not automount";
65} // Attributes::Setup()
srs5694e7b4ff92009-08-18 13:16:10 -040066
67// Display current attributes to user
68void Attributes::DisplayAttributes(void) {
srs56949ddc14b2010-08-22 22:44:42 -040069 uint32_t i;
70 int numSet = 0;
srs5694e7b4ff92009-08-18 13:16:10 -040071
srs5694fed16d02010-01-27 23:03:40 -050072 cout << "Attribute value is ";
73 cout.setf(ios::uppercase);
74 cout.fill('0');
75 cout.width(16);
76 cout << hex << attributes << dec << ". Set fields are:\n";
srs5694e7b4ff92009-08-18 13:16:10 -040077 for (i = 0; i < NUM_ATR; i++) {
srs56949ddc14b2010-08-22 22:44:42 -040078 if ((UINT64_C(1) << i) & attributes) {
srs56940873e9d2010-10-07 13:00:45 -040079 cout << i << " (" << GetAttributeName(i) << ")" << "\n";
srs56949ddc14b2010-08-22 22:44:42 -040080 numSet++;
srs5694e7b4ff92009-08-18 13:16:10 -040081 } // if
82 } // for
srs5694fed16d02010-01-27 23:03:40 -050083 cout.fill(' ');
srs56949ddc14b2010-08-22 22:44:42 -040084 if (numSet == 0)
85 cout << " No fields set\n";
86 cout << "\n";
srs5694e7b4ff92009-08-18 13:16:10 -040087} // Attributes::DisplayAttributes()
88
srs56940873e9d2010-10-07 13:00:45 -040089// Display attributes for a partition. Note that partNum is just passed for
90// immediate display; it's not used to access a particular partition.
91void Attributes::ShowAttributes(const uint32_t partNum) {
92 uint32_t bitNum;
93 bool bitset;
94
95 for (bitNum = 0; bitNum < 64; bitNum++) {
96 bitset = (UINT64_C(1) << bitNum) & attributes;
97 if (bitset) {
98 cout << partNum+1 << ":" << bitNum << ":" << bitset
99 << " (" << GetAttributeName(bitNum) << ")" << endl;
100 } // if
101 } // for
102} // Attributes::ShowAttributes
103
srs5694e7b4ff92009-08-18 13:16:10 -0400104// Prompt user for attribute changes
105void Attributes::ChangeAttributes(void) {
srs56949ddc14b2010-08-22 22:44:42 -0400106 int response;
srs5694e7b4ff92009-08-18 13:16:10 -0400107 uint64_t bitValue;
108
srs5694fed16d02010-01-27 23:03:40 -0500109 cout << "Known attributes are:\n";
srs56949ddc14b2010-08-22 22:44:42 -0400110 ListAttributes();
111 cout << "\n";
srs5694e7b4ff92009-08-18 13:16:10 -0400112
113 do {
srs56949ddc14b2010-08-22 22:44:42 -0400114 DisplayAttributes();
srs56940873e9d2010-10-07 13:00:45 -0400115 response = GetNumber(0, NUM_ATR, 64,
116 "Toggle which attribute field (0-63, 64 or <Enter> to exit): ");
srs5694e7b4ff92009-08-18 13:16:10 -0400117 if (response != 64) {
srs56949ddc14b2010-08-22 22:44:42 -0400118 bitValue = UINT64_C(1) << response; // Find the integer value of the bit
119 if (bitValue & attributes) { // bit is set
120 attributes &= ~bitValue; // so unset it
121 cout << "Have disabled the '" << atNames[response] << "' attribute.\n";
srs5694e7b4ff92009-08-18 13:16:10 -0400122 } else { // bit is not set
srs56949ddc14b2010-08-22 22:44:42 -0400123 attributes |= bitValue; // so set it
srs5694fed16d02010-01-27 23:03:40 -0500124 cout << "Have enabled the '" << atNames[response] << "' attribute.\n";
srs5694e7b4ff92009-08-18 13:16:10 -0400125 } // if/else
126 } // if
127 } while (response != 64);
128} // Attributes::ChangeAttributes()
129
srs56949ddc14b2010-08-22 22:44:42 -0400130// Display all defined attributes on the screen (omits undefined bits).
131void Attributes::ListAttributes(void) {
132 uint32_t bitNum;
133 string tempAttr;
134
135 for (bitNum = 0; bitNum < NUM_ATR; bitNum++) {
136 tempAttr = GetAttributeName(bitNum);
137 if (tempAttr.substr(0, 15) != "Undefined bit #" )
138 cout << bitNum << ": " << Attributes::GetAttributeName(bitNum) << "\n";
139 } // for
140} // Attributes::ListAttributes
141
srs56949ddc14b2010-08-22 22:44:42 -0400142// multifaceted attributes access
143// returns true upon success, false upon failure
144bool Attributes::OperateOnAttributes(const uint32_t partNum, const string& attributeOperator, const string& attributeBits) {
145
146 // attribute access opcode
147 typedef enum {
148 ao_or, ao_nand, ao_xor, ao_assignall, // operate on all attributes (bitmask)
149 ao_unknown, // must be after bitmask operators and before bitnum operators
150 ao_set, ao_clear, ao_toggle, ao_get // operate on a single attribute (bitnum)
151 } attribute_opcode_t; // typedef enum
152
153 // translate attribute operator into an attribute opcode
154 attribute_opcode_t attributeOpcode = ao_unknown; { // opcode is not known yet
155 if (attributeOperator == "or") attributeOpcode = ao_or;
156 else if (attributeOperator == "nand") attributeOpcode = ao_nand;
157 else if (attributeOperator == "xor") attributeOpcode = ao_xor;
158 else if (attributeOperator == "=") attributeOpcode = ao_assignall;
159 else if (attributeOperator == "set") attributeOpcode = ao_set;
160 else if (attributeOperator == "clear") attributeOpcode = ao_clear;
161 else if (attributeOperator == "toggle") attributeOpcode = ao_toggle;
162 else if (attributeOperator == "get") attributeOpcode = ao_get;
163 else {
164 cerr << "Unknown attributes operator: " << attributeOperator << endl;
165 return false;
166 } // else
167 } // attributeOpcode
168
169 // get bit mask if operating on entire attribute set
170 uint64_t attributeBitMask; { if (attributeOpcode < ao_unknown) {
171 if (1 != sscanf (attributeBits.c_str(), "%qx", (long long unsigned int*) &attributeBitMask)) {
172 cerr << "Could not convert hex attribute mask" << endl;
173 return false;
174 } // if
175 }} // attributeBitMask, if
176
177 // get bit number and calculate bit mask if operating on a single attribute
178 int bitNum; { if (attributeOpcode > ao_unknown) {
179 if (1 != sscanf (attributeBits.c_str(), "%d", &bitNum)) {
180 cerr << "Could not convert bit number" << endl;
181 return false;
182 } // if
183 const uint64_t one = 1;
184 attributeBitMask = one << bitNum;
185 }} // bitNum, if
186
187 switch (attributeOpcode) {
188 // assign all attributes at once
189 case ao_assignall: attributes = attributeBitMask; break;
190
191 // set individual attribute(s)
192 case ao_set:
193 case ao_or: attributes |= attributeBitMask; break;
194
195 // clear individual attribute(s)
196 case ao_clear:
197 case ao_nand: attributes &= ~attributeBitMask; break;
198
199 // toggle individual attribute(s)
200 case ao_toggle:
201 case ao_xor: attributes ^= attributeBitMask; break;
202
203 // display a single attribute
204 case ao_get: {
srs5694ab4b0432010-09-25 20:39:52 -0400205 cout << partNum+1 << ":" << bitNum << ":"
206 << bool (attributeBitMask & attributes) << endl;
srs56949ddc14b2010-08-22 22:44:42 -0400207 break;
208 } // case ao_get
209
210 default: break; // will never get here
211 } // switch
212
213 return true;
214} // Attributes::OperateOnAttributes()
srs56940873e9d2010-10-07 13:00:45 -0400215
216/*******************************
217* *
218* Non-class support functions *
219* *
220*******************************/
221
222// Display attributes
223ostream & operator<<(ostream & os, const Attributes & data) {
224 os << data.GetAttributes();
225 return os;
srs5694699941e2011-03-21 21:33:57 -0400226} // operator<<()